Libav 0.7.1
|
00001 /* 00002 * MPEG Audio parser 00003 * Copyright (c) 2003 Fabrice Bellard 00004 * Copyright (c) 2003 Michael Niedermayer 00005 * 00006 * This file is part of Libav. 00007 * 00008 * Libav 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 * Libav 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 Libav; 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 "mpegaudiodecheader.h" 00025 00026 00027 typedef struct MpegAudioParseContext { 00028 ParseContext pc; 00029 int frame_size; 00030 uint32_t header; 00031 int header_count; 00032 } MpegAudioParseContext; 00033 00034 #define MPA_HEADER_SIZE 4 00035 00036 /* header + layer + bitrate + freq + lsf/mpeg25 */ 00037 #define SAME_HEADER_MASK \ 00038 (0xffe00000 | (3 << 17) | (3 << 10) | (3 << 19)) 00039 00040 static int mpegaudio_parse(AVCodecParserContext *s1, 00041 AVCodecContext *avctx, 00042 const uint8_t **poutbuf, int *poutbuf_size, 00043 const uint8_t *buf, int buf_size) 00044 { 00045 MpegAudioParseContext *s = s1->priv_data; 00046 ParseContext *pc = &s->pc; 00047 uint32_t state= pc->state; 00048 int i; 00049 int next= END_NOT_FOUND; 00050 00051 for(i=0; i<buf_size; ){ 00052 if(s->frame_size){ 00053 int inc= FFMIN(buf_size - i, s->frame_size); 00054 i += inc; 00055 s->frame_size -= inc; 00056 00057 if(!s->frame_size){ 00058 next= i; 00059 break; 00060 } 00061 }else{ 00062 while(i<buf_size){ 00063 int ret, sr, channels, bit_rate, frame_size; 00064 00065 state= (state<<8) + buf[i++]; 00066 00067 ret = ff_mpa_decode_header(avctx, state, &sr, &channels, &frame_size, &bit_rate); 00068 if (ret < 4) { 00069 s->header_count= -2; 00070 } else { 00071 if((state&SAME_HEADER_MASK) != (s->header&SAME_HEADER_MASK) && s->header) 00072 s->header_count= -3; 00073 s->header= state; 00074 s->header_count++; 00075 s->frame_size = ret-4; 00076 00077 if(s->header_count > 1){ 00078 avctx->sample_rate= sr; 00079 avctx->channels = channels; 00080 avctx->frame_size = frame_size; 00081 avctx->bit_rate = bit_rate; 00082 } 00083 break; 00084 } 00085 } 00086 } 00087 } 00088 00089 pc->state= state; 00090 if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { 00091 *poutbuf = NULL; 00092 *poutbuf_size = 0; 00093 return buf_size; 00094 } 00095 00096 *poutbuf = buf; 00097 *poutbuf_size = buf_size; 00098 return next; 00099 } 00100 00101 00102 AVCodecParser ff_mpegaudio_parser = { 00103 { CODEC_ID_MP1, CODEC_ID_MP2, CODEC_ID_MP3 }, 00104 sizeof(MpegAudioParseContext), 00105 NULL, 00106 mpegaudio_parse, 00107 ff_parse_close, 00108 };