📄 audio.c
字号:
/******************************************************************************* 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 + -