libavcodec/dnxhd_parser.c
da396bf8
 /*
  * DNxHD/VC-3 parser
  * Copyright (c) 2008 Baptiste Coudurier <baptiste.coudurier@free.fr>
  *
  * This file is part of FFmpeg.
  *
  * FFmpeg 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.
  *
  * FFmpeg 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 FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 /**
ba87f080
  * @file
da396bf8
  * DNxHD/VC-3 parser
  */
 
 #include "parser.h"
8395b6ee
 #include "dnxhddata.h"
da396bf8
 
76068253
 typedef struct {
     ParseContext pc;
e1940d24
     int cur_byte;
     int remaining;
     int w, h;
76068253
 } DNXHDParserContext;
 
 static int dnxhd_find_frame_end(DNXHDParserContext *dctx,
da396bf8
                                 const uint8_t *buf, int buf_size)
 {
76068253
     ParseContext *pc = &dctx->pc;
da396bf8
     uint64_t state = pc->state64;
     int pic_found = pc->frame_start_found;
     int i = 0;
 
     if (!pic_found) {
         for (i = 0; i < buf_size; i++) {
89ef08c9
             state = (state << 8) | buf[i];
8395b6ee
             if (ff_dnxhd_check_header_prefix(state & 0xffffffffff00LL) != 0) {
da396bf8
                 i++;
                 pic_found = 1;
e1940d24
                 dctx->cur_byte = 0;
                 dctx->remaining = 0;
da396bf8
                 break;
             }
         }
     }
 
e1940d24
     if (pic_found && !dctx->remaining) {
da396bf8
         if (!buf_size) /* EOF considered as end of frame */
             return 0;
         for (; i < buf_size; i++) {
e1940d24
             dctx->cur_byte++;
89ef08c9
             state = (state << 8) | buf[i];
e1940d24
 
             if (dctx->cur_byte == 24) {
                 dctx->h = (state >> 32) & 0xFFFF;
             } else if (dctx->cur_byte == 26) {
                 dctx->w = (state >> 32) & 0xFFFF;
             } else if (dctx->cur_byte == 42) {
                 int cid = (state >> 32) & 0xFFFFFFFF;
611b3562
                 int remaining;
e1940d24
 
                 if (cid <= 0)
                     continue;
 
611b3562
                 remaining = avpriv_dnxhd_get_frame_size(cid);
                 if (remaining <= 0) {
                     remaining = ff_dnxhd_get_hr_frame_size(cid, dctx->w, dctx->h);
                     if (remaining <= 0)
                         continue;
e1940d24
                 }
190b9235
                 remaining += i - 47;
611b3562
                 dctx->remaining = remaining;
190b9235
                 if (buf_size >= dctx->remaining) {
76068253
                     pc->frame_start_found = 0;
                     pc->state64 = -1;
e1940d24
                     dctx->cur_byte = 0;
                     dctx->remaining = 0;
                     return remaining;
76068253
                 } else {
e1940d24
                     dctx->remaining -= buf_size;
76068253
                 }
da396bf8
             }
         }
e1940d24
     } else if (pic_found) {
         if (dctx->remaining > buf_size) {
             dctx->remaining -= buf_size;
         } else {
             int remaining = dctx->remaining;
 
             pc->frame_start_found = 0;
             pc->state64 = -1;
             dctx->cur_byte = 0;
             dctx->remaining = 0;
             return remaining;
         }
da396bf8
     }
     pc->frame_start_found = pic_found;
     pc->state64 = state;
     return END_NOT_FOUND;
 }
 
 static int dnxhd_parse(AVCodecParserContext *s,
                        AVCodecContext *avctx,
                        const uint8_t **poutbuf, int *poutbuf_size,
                        const uint8_t *buf, int buf_size)
 {
76068253
     DNXHDParserContext *dctx = s->priv_data;
     ParseContext *pc = &dctx->pc;
da396bf8
     int next;
 
     if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
         next = buf_size;
     } else {
76068253
         next = dnxhd_find_frame_end(dctx, buf, buf_size);
da396bf8
         if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
89ef08c9
             *poutbuf      = NULL;
da396bf8
             *poutbuf_size = 0;
             return buf_size;
         }
     }
89ef08c9
     *poutbuf      = buf;
da396bf8
     *poutbuf_size = buf_size;
     return next;
 }
 
e7e2df27
 AVCodecParser ff_dnxhd_parser = {
36ef5369
     .codec_ids      = { AV_CODEC_ID_DNXHD },
76068253
     .priv_data_size = sizeof(DNXHDParserContext),
5511ad14
     .parser_parse   = dnxhd_parse,
     .parser_close   = ff_parse_close,
da396bf8
 };