Libav 0.7.1
|
00001 /* 00002 * MPEG4 Video frame extraction 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 "mpegvideo.h" 00025 #include "mpeg4video.h" 00026 #include "mpeg4video_parser.h" 00027 00028 00029 int ff_mpeg4_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size){ 00030 int vop_found, i; 00031 uint32_t state; 00032 00033 vop_found= pc->frame_start_found; 00034 state= pc->state; 00035 00036 i=0; 00037 if(!vop_found){ 00038 for(i=0; i<buf_size; i++){ 00039 state= (state<<8) | buf[i]; 00040 if(state == 0x1B6){ 00041 i++; 00042 vop_found=1; 00043 break; 00044 } 00045 } 00046 } 00047 00048 if(vop_found){ 00049 /* EOF considered as end of frame */ 00050 if (buf_size == 0) 00051 return 0; 00052 for(; i<buf_size; i++){ 00053 state= (state<<8) | buf[i]; 00054 if((state&0xFFFFFF00) == 0x100){ 00055 pc->frame_start_found=0; 00056 pc->state=-1; 00057 return i-3; 00058 } 00059 } 00060 } 00061 pc->frame_start_found= vop_found; 00062 pc->state= state; 00063 return END_NOT_FOUND; 00064 } 00065 00066 /* XXX: make it use less memory */ 00067 static int av_mpeg4_decode_header(AVCodecParserContext *s1, 00068 AVCodecContext *avctx, 00069 const uint8_t *buf, int buf_size) 00070 { 00071 ParseContext1 *pc = s1->priv_data; 00072 MpegEncContext *s = pc->enc; 00073 GetBitContext gb1, *gb = &gb1; 00074 int ret; 00075 00076 s->avctx = avctx; 00077 s->current_picture_ptr = &s->current_picture; 00078 00079 if (avctx->extradata_size && pc->first_picture){ 00080 init_get_bits(gb, avctx->extradata, avctx->extradata_size*8); 00081 ret = ff_mpeg4_decode_picture_header(s, gb); 00082 } 00083 00084 init_get_bits(gb, buf, 8 * buf_size); 00085 ret = ff_mpeg4_decode_picture_header(s, gb); 00086 if (s->width && (!avctx->width || !avctx->height || !avctx->coded_width || !avctx->coded_height)) { 00087 avcodec_set_dimensions(avctx, s->width, s->height); 00088 } 00089 s1->pict_type= s->pict_type; 00090 pc->first_picture = 0; 00091 return ret; 00092 } 00093 00094 static av_cold int mpeg4video_parse_init(AVCodecParserContext *s) 00095 { 00096 ParseContext1 *pc = s->priv_data; 00097 00098 pc->enc = av_mallocz(sizeof(MpegEncContext)); 00099 if (!pc->enc) 00100 return -1; 00101 pc->first_picture = 1; 00102 return 0; 00103 } 00104 00105 static int mpeg4video_parse(AVCodecParserContext *s, 00106 AVCodecContext *avctx, 00107 const uint8_t **poutbuf, int *poutbuf_size, 00108 const uint8_t *buf, int buf_size) 00109 { 00110 ParseContext *pc = s->priv_data; 00111 int next; 00112 00113 if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){ 00114 next= buf_size; 00115 }else{ 00116 next= ff_mpeg4_find_frame_end(pc, buf, buf_size); 00117 00118 if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { 00119 *poutbuf = NULL; 00120 *poutbuf_size = 0; 00121 return buf_size; 00122 } 00123 } 00124 av_mpeg4_decode_header(s, avctx, buf, buf_size); 00125 00126 *poutbuf = buf; 00127 *poutbuf_size = buf_size; 00128 return next; 00129 } 00130 00131 00132 AVCodecParser ff_mpeg4video_parser = { 00133 { CODEC_ID_MPEG4 }, 00134 sizeof(ParseContext1), 00135 mpeg4video_parse_init, 00136 mpeg4video_parse, 00137 ff_parse1_close, 00138 ff_mpeg4video_split, 00139 };