Libav
|
00001 /* 00002 * MPEG Audio parser 00003 * Copyright (c) 2003 Fabrice Bellard 00004 * Copyright (c) 2003 Michael Niedermayer 00005 * 00006 * This file is part of FFmpeg. 00007 * 00008 * FFmpeg is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * FFmpeg is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with FFmpeg; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 */ 00022 00023 #include "parser.h" 00024 #include "mpegaudio.h" 00025 #include "mpegaudiodecheader.h" 00026 00027 00028 typedef struct MpegAudioParseContext { 00029 ParseContext pc; 00030 int frame_size; 00031 uint32_t header; 00032 int header_count; 00033 } MpegAudioParseContext; 00034 00035 #define MPA_HEADER_SIZE 4 00036 00037 /* header + layer + bitrate + freq + lsf/mpeg25 */ 00038 #undef SAME_HEADER_MASK /* mpegaudio.h defines different version */ 00039 #define SAME_HEADER_MASK \ 00040 (0xffe00000 | (3 << 17) | (3 << 10) | (3 << 19)) 00041 00042 /* useful helper to get mpeg audio stream infos. Return -1 if error in 00043 header, otherwise the coded frame size in bytes */ 00044 int ff_mpa_decode_header(AVCodecContext *avctx, uint32_t head, int *sample_rate, int *channels, int *frame_size, int *bit_rate) 00045 { 00046 MPADecodeHeader s1, *s = &s1; 00047 00048 if (ff_mpa_check_header(head) != 0) 00049 return -1; 00050 00051 if (ff_mpegaudio_decode_header(s, head) != 0) { 00052 return -1; 00053 } 00054 00055 switch(s->layer) { 00056 case 1: 00057 avctx->codec_id = CODEC_ID_MP1; 00058 *frame_size = 384; 00059 break; 00060 case 2: 00061 avctx->codec_id = CODEC_ID_MP2; 00062 *frame_size = 1152; 00063 break; 00064 default: 00065 case 3: 00066 avctx->codec_id = CODEC_ID_MP3; 00067 if (s->lsf) 00068 *frame_size = 576; 00069 else 00070 *frame_size = 1152; 00071 break; 00072 } 00073 00074 *sample_rate = s->sample_rate; 00075 *channels = s->nb_channels; 00076 *bit_rate = s->bit_rate; 00077 avctx->sub_id = s->layer; 00078 return s->frame_size; 00079 } 00080 00081 static int mpegaudio_parse(AVCodecParserContext *s1, 00082 AVCodecContext *avctx, 00083 const uint8_t **poutbuf, int *poutbuf_size, 00084 const uint8_t *buf, int buf_size) 00085 { 00086 MpegAudioParseContext *s = s1->priv_data; 00087 ParseContext *pc = &s->pc; 00088 uint32_t state= pc->state; 00089 int i; 00090 int next= END_NOT_FOUND; 00091 00092 for(i=0; i<buf_size; ){ 00093 if(s->frame_size){ 00094 int inc= FFMIN(buf_size - i, s->frame_size); 00095 i += inc; 00096 s->frame_size -= inc; 00097 00098 if(!s->frame_size){ 00099 next= i; 00100 break; 00101 } 00102 }else{ 00103 while(i<buf_size){ 00104 int ret, sr, channels, bit_rate, frame_size; 00105 00106 state= (state<<8) + buf[i++]; 00107 00108 ret = ff_mpa_decode_header(avctx, state, &sr, &channels, &frame_size, &bit_rate); 00109 if (ret < 4) { 00110 s->header_count= -2; 00111 } else { 00112 if((state&SAME_HEADER_MASK) != (s->header&SAME_HEADER_MASK) && s->header) 00113 s->header_count= -3; 00114 s->header= state; 00115 s->header_count++; 00116 s->frame_size = ret-4; 00117 00118 if(s->header_count > 1){ 00119 avctx->sample_rate= sr; 00120 avctx->channels = channels; 00121 avctx->frame_size = frame_size; 00122 avctx->bit_rate = bit_rate; 00123 } 00124 break; 00125 } 00126 } 00127 } 00128 } 00129 00130 pc->state= state; 00131 if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { 00132 *poutbuf = NULL; 00133 *poutbuf_size = 0; 00134 return buf_size; 00135 } 00136 00137 *poutbuf = buf; 00138 *poutbuf_size = buf_size; 00139 return next; 00140 } 00141 00142 00143 AVCodecParser mpegaudio_parser = { 00144 { CODEC_ID_MP1, CODEC_ID_MP2, CODEC_ID_MP3 }, 00145 sizeof(MpegAudioParseContext), 00146 NULL, 00147 mpegaudio_parse, 00148 ff_parse_close, 00149 };