Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * MPEG4 Video frame extraction
  3.  * Copyright (c) 2003 Fabrice Bellard
  4.  * Copyright (c) 2003 Michael Niedermayer
  5.  *
  6.  * This file is part of FFmpeg.
  7.  *
  8.  * FFmpeg is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Lesser General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2.1 of the License, or (at your option) any later version.
  12.  *
  13.  * FFmpeg is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Lesser General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Lesser General Public
  19.  * License along with FFmpeg; if not, write to the Free Software
  20.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21.  */
  22.  
  23. #define UNCHECKED_BITSTREAM_READER 1
  24.  
  25. #include "parser.h"
  26. #include "mpegvideo.h"
  27. #include "mpeg4video.h"
  28. #include "mpeg4video_parser.h"
  29.  
  30. struct Mp4vParseContext {
  31.     ParseContext pc;
  32.     struct MpegEncContext enc;
  33.     int first_picture;
  34. };
  35.  
  36. int ff_mpeg4_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size){
  37.     int vop_found, i;
  38.     uint32_t state;
  39.  
  40.     vop_found= pc->frame_start_found;
  41.     state= pc->state;
  42.  
  43.     i=0;
  44.     if(!vop_found){
  45.         for(i=0; i<buf_size; i++){
  46.             state= (state<<8) | buf[i];
  47.             if(state == 0x1B6){
  48.                 i++;
  49.                 vop_found=1;
  50.                 break;
  51.             }
  52.         }
  53.     }
  54.  
  55.     if(vop_found){
  56.         /* EOF considered as end of frame */
  57.         if (buf_size == 0)
  58.             return 0;
  59.         for(; i<buf_size; i++){
  60.             state= (state<<8) | buf[i];
  61.             if((state&0xFFFFFF00) == 0x100){
  62.                 pc->frame_start_found=0;
  63.                 pc->state=-1;
  64.                 return i-3;
  65.             }
  66.         }
  67.     }
  68.     pc->frame_start_found= vop_found;
  69.     pc->state= state;
  70.     return END_NOT_FOUND;
  71. }
  72.  
  73. /* XXX: make it use less memory */
  74. static int av_mpeg4_decode_header(AVCodecParserContext *s1,
  75.                                   AVCodecContext *avctx,
  76.                                   const uint8_t *buf, int buf_size)
  77. {
  78.     struct Mp4vParseContext *pc = s1->priv_data;
  79.     MpegEncContext *s = &pc->enc;
  80.     GetBitContext gb1, *gb = &gb1;
  81.     int ret;
  82.  
  83.     s->avctx = avctx;
  84.     s->current_picture_ptr = &s->current_picture;
  85.  
  86.     if (avctx->extradata_size && pc->first_picture){
  87.         init_get_bits(gb, avctx->extradata, avctx->extradata_size*8);
  88.         ret = ff_mpeg4_decode_picture_header(s, gb);
  89.     }
  90.  
  91.     init_get_bits(gb, buf, 8 * buf_size);
  92.     ret = ff_mpeg4_decode_picture_header(s, gb);
  93.     if (s->width && (!avctx->width || !avctx->height || !avctx->coded_width || !avctx->coded_height)) {
  94.         avcodec_set_dimensions(avctx, s->width, s->height);
  95.     }
  96.     if((s1->flags & PARSER_FLAG_USE_CODEC_TS) && s->avctx->time_base.den>0 && ret>=0){
  97.         av_assert1(s1->pts == AV_NOPTS_VALUE);
  98.         av_assert1(s1->dts == AV_NOPTS_VALUE);
  99.  
  100.         s1->pts = av_rescale_q(s->time, (AVRational){1, s->avctx->time_base.den}, (AVRational){1, 1200000});
  101.     }
  102.  
  103.     s1->pict_type= s->pict_type;
  104.     pc->first_picture = 0;
  105.     return ret;
  106. }
  107.  
  108. static av_cold int mpeg4video_parse_init(AVCodecParserContext *s)
  109. {
  110.     struct Mp4vParseContext *pc = s->priv_data;
  111.  
  112.     ff_mpeg4videodec_static_init();
  113.  
  114.     pc->first_picture = 1;
  115.     pc->enc.quant_precision=5;
  116.     pc->enc.slice_context_count = 1;
  117.     pc->enc.showed_packed_warning = 1;
  118.     return 0;
  119. }
  120.  
  121. static int mpeg4video_parse(AVCodecParserContext *s,
  122.                            AVCodecContext *avctx,
  123.                            const uint8_t **poutbuf, int *poutbuf_size,
  124.                            const uint8_t *buf, int buf_size)
  125. {
  126.     ParseContext *pc = s->priv_data;
  127.     int next;
  128.  
  129.     if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){
  130.         next= buf_size;
  131.     }else{
  132.         next= ff_mpeg4_find_frame_end(pc, buf, buf_size);
  133.  
  134.         if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
  135.             *poutbuf = NULL;
  136.             *poutbuf_size = 0;
  137.             return buf_size;
  138.         }
  139.     }
  140.     av_mpeg4_decode_header(s, avctx, buf, buf_size);
  141.  
  142.     *poutbuf = buf;
  143.     *poutbuf_size = buf_size;
  144.     return next;
  145. }
  146.  
  147.  
  148. AVCodecParser ff_mpeg4video_parser = {
  149.     .codec_ids      = { AV_CODEC_ID_MPEG4 },
  150.     .priv_data_size = sizeof(struct Mp4vParseContext),
  151.     .parser_init    = mpeg4video_parse_init,
  152.     .parser_parse   = mpeg4video_parse,
  153.     .parser_close   = ff_parse_close,
  154.     .split          = ff_mpeg4video_split,
  155. };
  156.