⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audio.c

📁 这个库实现了录象功能
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************* audio.c libquicktime - A library for reading and writing quicktime/avi/mp4 files. http://libquicktime.sourceforge.net Copyright (C) 2002 Heroine Virtual Ltd. Copyright (C) 2002-2007 Members of the libquicktime project. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA*******************************************************************************/ #include "lqt_private.h"#include "ffmpeg.h"#define LQT_LIBQUICKTIME#include <quicktime/lqt_codecapi.h>#include <stdlib.h>#include <string.h>#define LOG_DOMAIN "ffmpeg_audio"/* Different decoding functions */#if LIBAVCODEC_BUILD >= 3349760#define DECODE_FUNC avcodec_decode_audio2#else#define DECODE_FUNC avcodec_decode_audio#endif/* The following code was ported from gmerlin_avdecoder (http://gmerlin.sourceforge.net) *//* MPEG Audio header parsing code */static int mpeg_bitrates[5][16] = {  /* MPEG-1 */  { 0,  32000,  64000,  96000, 128000, 160000, 192000, 224000,    // I       256000, 288000, 320000, 352000, 384000, 416000, 448000, 0},  { 0,  32000,  48000,  56000,  64000,  80000,  96000, 112000,    // II       128000, 160000, 192000, 224000, 256000, 320000, 384000, 0 },  { 0,  32000,  40000,  48000,  56000,  64000,  80000,  96000,    // III       112000, 128000, 160000, 192000, 224000, 256000, 320000, 0 },  /* MPEG-2 LSF */  { 0,  32000,  48000,  56000,  64000,  80000,  96000, 112000,    // I       128000, 144000, 160000, 176000, 192000, 224000, 256000, 0 },  { 0,   8000,  16000,  24000,  32000,  40000,  48000,  56000,        64000,  80000,  96000, 112000, 128000, 144000, 160000, 0 } // II & III};static int mpeg_samplerates[3][3] = {  { 44100, 48000, 32000 }, // MPEG1  { 22050, 24000, 16000 }, // MPEG2  { 11025, 12000, 8000 }   // MPEG2.5  };#define MPEG_ID_MASK        0x00180000#define MPEG_MPEG1          0x00180000#define MPEG_MPEG2          0x00100000#define MPEG_MPEG2_5        0x00000000#define MPEG_LAYER_MASK     0x00060000#define MPEG_LAYER_III      0x00020000#define MPEG_LAYER_II       0x00040000#define MPEG_LAYER_I        0x00060000#define MPEG_PROTECTION     0x00010000#define MPEG_BITRATE_MASK   0x0000F000#define MPEG_FREQUENCY_MASK 0x00000C00#define MPEG_PAD_MASK       0x00000200#define MPEG_PRIVATE_MASK   0x00000100#define MPEG_MODE_MASK      0x000000C0#define MPEG_MODE_EXT_MASK  0x00000030#define MPEG_COPYRIGHT_MASK 0x00000008#define MPEG_HOME_MASK      0x00000004#define MPEG_EMPHASIS_MASK  0x00000003#define LAYER_I_SAMPLES       384#define LAYER_II_III_SAMPLES 1152/* Header detection stolen from the mpg123 plugin of xmms */static int header_check(uint32_t head){        if ((head & 0xffe00000) != 0xffe00000)                return 0;        if (!((head >> 17) & 3))                return 0;        if (((head >> 12) & 0xf) == 0xf)                return 0;        if (!((head >> 12) & 0xf))                return 0;        if (((head >> 10) & 0x3) == 0x3)                return 0;        if (((head >> 19) & 1) == 1 &&            ((head >> 17) & 3) == 3 &&            ((head >> 16) & 1) == 1)                return 0;        if ((head & 0xffff0000) == 0xfffe0000)                return 0;        return 1;}typedef enum  {    MPEG_VERSION_NONE = 0,    MPEG_VERSION_1 = 1,    MPEG_VERSION_2 = 2,    MPEG_VERSION_2_5  } mpeg_version_t;#define CHANNEL_STEREO   0#define CHANNEL_JSTEREO  1#define CHANNEL_DUAL     2#define CHANNEL_MONO     3typedef struct  {  mpeg_version_t version;  int layer;  int bitrate;    /* -1: VBR */  int samplerate;  int frame_bytes;  int channel_mode;  int mode;  int samples_per_frame;  } mpeg_header;static int header_equal(const mpeg_header * h1, const mpeg_header * h2)  {  return ((h1->layer == h2->layer) && (h1->version == h2->version) &&          (h1->samplerate == h2->samplerate));  }static int decode_header(mpeg_header * h, uint8_t * ptr, const mpeg_header * ref)  {  uint32_t header;  int index;  /* For calculation of the byte length of a frame */  int pad;  int slots_per_frame;  h->frame_bytes = 0;  header =    ptr[3] | (ptr[2] << 8) | (ptr[1] << 16) | (ptr[0] << 24);  if(!header_check(header))    return 0;  index = (header & MPEG_MODE_MASK) >> 6;  switch(index)    {    case 0:      h->channel_mode = CHANNEL_STEREO;      break;    case 1:      h->channel_mode = CHANNEL_JSTEREO;      break;    case 2:      h->channel_mode = CHANNEL_DUAL;      break;    case 3:      h->channel_mode = CHANNEL_MONO;      break;    }  /* Get Version */  switch(header & MPEG_ID_MASK)    {    case MPEG_MPEG1:      h->version = MPEG_VERSION_1;        break;    case MPEG_MPEG2:      h->version = MPEG_VERSION_2;      break;    case MPEG_MPEG2_5:      h->version = MPEG_VERSION_2_5;      break;    default:      return 0;    }  /* Get Layer */  switch(header & MPEG_LAYER_MASK)    {    case MPEG_LAYER_I:      h->layer = 1;      break;    case MPEG_LAYER_II:      h->layer = 2;      break;    case MPEG_LAYER_III:      h->layer = 3;      break;    }  index = (header & MPEG_BITRATE_MASK) >> 12;  switch(h->version)    {    case MPEG_VERSION_1:      switch(h->layer)        {        case 1:          h->bitrate = mpeg_bitrates[0][index];          break;        case 2:          h->bitrate = mpeg_bitrates[1][index];          break;        case 3:          h->bitrate = mpeg_bitrates[2][index];          break;        }      break;    case MPEG_VERSION_2:    case MPEG_VERSION_2_5:      switch(h->layer)        {        case 1:          h->bitrate = mpeg_bitrates[3][index];          break;        case 2:        case 3:          h->bitrate = mpeg_bitrates[4][index];          break;        }      break;    default: // This won't happen, but keeps gcc quiet      return 0;    }  index = (header & MPEG_FREQUENCY_MASK) >> 10;  switch(h->version)    {    case MPEG_VERSION_1:      h->samplerate = mpeg_samplerates[0][index];      break;    case MPEG_VERSION_2:      h->samplerate = mpeg_samplerates[1][index];      break;    case MPEG_VERSION_2_5:      h->samplerate = mpeg_samplerates[2][index];      break;    default: // This won't happen, but keeps gcc quiet      return 0;    }  pad = (header & MPEG_PAD_MASK) ? 1 : 0;  if(h->layer == 1)    {    h->frame_bytes = ((12 * h->bitrate / h->samplerate) + pad) * 4;    }  else    {    slots_per_frame = ((h->layer == 3) &&      ((h->version == MPEG_VERSION_2) ||       (h->version == MPEG_VERSION_2_5))) ? 72 : 144;    h->frame_bytes = (slots_per_frame * h->bitrate) / h->samplerate + pad;    }  // h->mode = (ptr[3] >> 6) & 3;  h->samples_per_frame =    (h->layer == 1) ? LAYER_I_SAMPLES : LAYER_II_III_SAMPLES;  if(h->version != MPEG_VERSION_1)    h->samples_per_frame /= 2;  //  dump_header(h);  /* Check against reference header */  if(ref && !header_equal(ref, h))    return 0;  return 1;  }typedef struct  {  AVCodecContext * avctx;  AVCodec * encoder;  AVCodec * decoder;  int initialized;    /* Interleaved samples as avcodec needs them */      int16_t * sample_buffer;  int sample_buffer_alloc;   int samples_in_buffer;    /* Buffer for the entire chunk */  uint8_t * chunk_buffer;  int chunk_buffer_alloc;  int bytes_in_chunk_buffer;  /* Start and end positions of the sample buffer */      int64_t sample_buffer_start;  int64_t sample_buffer_end;  mpeg_header mph;  int have_mpeg_header;  uint8_t * extradata;      } quicktime_ffmpeg_audio_codec_t;static int lqt_ffmpeg_delete_audio(quicktime_audio_map_t *vtrack)  {  quicktime_ffmpeg_audio_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;    if(codec->avctx)    {    if(codec->initialized)      avcodec_close(codec->avctx);    av_free(codec->avctx);    }  if(codec->sample_buffer) free(codec->sample_buffer);  if(codec->chunk_buffer)  free(codec->chunk_buffer);  if(codec->extradata) free(codec->extradata);   free(codec);  return 0;  }static int set_parameter(quicktime_t *file,                   int track,                   const char *key,                   const void *value)  {  quicktime_ffmpeg_audio_codec_t *codec = ((quicktime_codec_t*)file->atracks[track].codec)->priv;  lqt_ffmpeg_set_parameter(codec->avctx, key, value);  return 0;  }/* Decode VBR chunk into the sample buffer */static int decode_chunk_vbr(quicktime_t * file, int track)  {  int chunk_packets, i, num_samples, bytes_decoded;  int packet_size, packet_samples;  int frame_bytes;  int new_samples;  quicktime_audio_map_t *track_map = &(file->atracks[track]);  quicktime_ffmpeg_audio_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;  chunk_packets = lqt_audio_num_vbr_packets(file, track, track_map->current_chunk, &num_samples);  if(!chunk_packets)    return 0;  new_samples = num_samples + AVCODEC_MAX_AUDIO_FRAME_SIZE / (2 * track_map->channels);    if(codec->sample_buffer_alloc <     codec->sample_buffer_end - codec->sample_buffer_start + new_samples)    {        codec->sample_buffer_alloc = codec->sample_buffer_end - codec->sample_buffer_start + new_samples;    codec->sample_buffer = realloc(codec->sample_buffer, 2 * codec->sample_buffer_alloc *                                   track_map->channels);    }  for(i = 0; i < chunk_packets; i++)    {    packet_size = lqt_audio_read_vbr_packet(file, track, track_map->current_chunk, i,                                            &(codec->chunk_buffer), &(codec->chunk_buffer_alloc),                                            &packet_samples);    if(!packet_size)      return 0;#if LIBAVCODEC_BUILD >= 3349760    bytes_decoded = codec->sample_buffer_alloc -      (codec->sample_buffer_end - codec->sample_buffer_start);    bytes_decoded *= 2 * track_map->channels;#else    bytes_decoded = 0;#endif        frame_bytes =      DECODE_FUNC(codec->avctx,                  &(codec->sample_buffer[track_map->channels *                                         (codec->sample_buffer_end - codec->sample_buffer_start)]),                  &bytes_decoded,                  codec->chunk_buffer,                  packet_size + FF_INPUT_BUFFER_PADDING_SIZE);    if(frame_bytes < 0)      {      lqt_log(file, LQT_LOG_ERROR, LOG_DOMAIN, "avcodec_decode_audio error");      break;      }    codec->sample_buffer_end += (bytes_decoded / (track_map->channels * 2));    }  track_map->current_chunk++;  return num_samples;  }/* Decode the current chunk into the sample buffer */static int decode_chunk(quicktime_t * file, int track)  {  mpeg_header mph;      int frame_bytes;  int num_samples;  int new_samples;  int samples_decoded = 0;  int bytes_decoded;  int bytes_used, bytes_skipped;  int64_t chunk_size;  quicktime_audio_map_t *track_map = &(file->atracks[track]);  quicktime_ffmpeg_audio_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;  /* Read chunk */    chunk_size = lqt_append_audio_chunk(file,                                      track, track_map->current_chunk,                                      &(codec->chunk_buffer),                                      &(codec->chunk_buffer_alloc),                                      codec->bytes_in_chunk_buffer);    if(!chunk_size)    {    /* If the codec is mp3, make sure to decode the very last frame */    if((codec->avctx->codec_id == CODEC_ID_MP3) &&       (codec->bytes_in_chunk_buffer >= 4))      {      if(!decode_header(&mph, codec->chunk_buffer, (const mpeg_header*)0))        {        lqt_log(file, LQT_LOG_ERROR, LOG_DOMAIN, "Decode header failed");        return 0;        }      if(mph.frame_bytes <= codec->bytes_in_chunk_buffer)        {        lqt_log(file, LQT_LOG_ERROR, LOG_DOMAIN, "Huh, frame not decoded?");        return 0;        }      if(codec->chunk_buffer_alloc < mph.frame_bytes + FF_INPUT_BUFFER_PADDING_SIZE)        {        codec->chunk_buffer_alloc = mph.frame_bytes + FF_INPUT_BUFFER_PADDING_SIZE;        codec->chunk_buffer = realloc(codec->chunk_buffer, codec->chunk_buffer_alloc);        }      memset(codec->chunk_buffer + codec->bytes_in_chunk_buffer, 0,             mph.frame_bytes - codec->bytes_in_chunk_buffer + FF_INPUT_BUFFER_PADDING_SIZE);      num_samples = mph.samples_per_frame;      codec->bytes_in_chunk_buffer = mph.frame_bytes;      }    else      return 0;    }  else    {    num_samples = quicktime_chunk_samples(track_map->track, track_map->current_chunk);    track_map->current_chunk++;    codec->bytes_in_chunk_buffer += chunk_size;    }    if(!num_samples)    {    return 0;    }  /*   *  For AVIs, chunk samples are not always 100% correct.   *  Furthermore, there can be a complete mp3 frame from the last chunk!   */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -