1/* 2 * DNxHD/VC-3 parser 3 * Copyright (c) 2008 Baptiste Coudurier <baptiste.coudurier@free.fr> 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/** 23 * @file 24 * DNxHD/VC-3 parser 25 */ 26 27#include "parser.h" 28#include "dnxhddata.h" 29 30typedef struct { 31 ParseContext pc; 32 int cur_byte; 33 int remaining; 34 int w, h; 35} DNXHDParserContext; 36 37static int dnxhd_find_frame_end(DNXHDParserContext *dctx, 38 const uint8_t *buf, int buf_size) 39{ 40 ParseContext *pc = &dctx->pc; 41 uint64_t state = pc->state64; 42 int pic_found = pc->frame_start_found; 43 int i = 0; 44 45 if (!pic_found) { 46 for (i = 0; i < buf_size; i++) { 47 state = (state << 8) | buf[i]; 48 if (ff_dnxhd_check_header_prefix(state & 0xffffffffff00LL) != 0) { 49 i++; 50 pic_found = 1; 51 dctx->cur_byte = 0; 52 dctx->remaining = 0; 53 break; 54 } 55 } 56 } 57 58 if (pic_found && !dctx->remaining) { 59 if (!buf_size) /* EOF considered as end of frame */ 60 return 0; 61 for (; i < buf_size; i++) { 62 dctx->cur_byte++; 63 state = (state << 8) | buf[i]; 64 65 if (dctx->cur_byte == 24) { 66 dctx->h = (state >> 32) & 0xFFFF; 67 } else if (dctx->cur_byte == 26) { 68 dctx->w = (state >> 32) & 0xFFFF; 69 } else if (dctx->cur_byte == 42) { 70 int cid = (state >> 32) & 0xFFFFFFFF; 71 int remaining; 72 73 if (cid <= 0) 74 continue; 75 76 remaining = ff_dnxhd_get_frame_size(cid); 77 if (remaining <= 0) { 78 remaining = ff_dnxhd_get_hr_frame_size(cid, dctx->w, dctx->h); 79 if (remaining <= 0) 80 continue; 81 } 82 remaining += i - 47; 83 dctx->remaining = remaining; 84 if (buf_size >= dctx->remaining) { 85 pc->frame_start_found = 0; 86 pc->state64 = -1; 87 dctx->cur_byte = 0; 88 dctx->remaining = 0; 89 return remaining; 90 } else { 91 dctx->remaining -= buf_size; 92 // Update variables for correctness, they are currently not used beyond here 93 state = -1; 94 dctx->cur_byte += buf_size - i; 95 break; 96 } 97 } 98 } 99 } else if (pic_found) { 100 if (dctx->remaining > buf_size) { 101 dctx->remaining -= buf_size; 102 } else { 103 int remaining = dctx->remaining; 104 105 pc->frame_start_found = 0; 106 pc->state64 = -1; 107 dctx->cur_byte = 0; 108 dctx->remaining = 0; 109 return remaining; 110 } 111 } 112 pc->frame_start_found = pic_found; 113 pc->state64 = state; 114 return END_NOT_FOUND; 115} 116 117static int dnxhd_parse(AVCodecParserContext *s, 118 AVCodecContext *avctx, 119 const uint8_t **poutbuf, int *poutbuf_size, 120 const uint8_t *buf, int buf_size) 121{ 122 DNXHDParserContext *dctx = s->priv_data; 123 ParseContext *pc = &dctx->pc; 124 int next; 125 126 if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { 127 next = buf_size; 128 } else { 129 next = dnxhd_find_frame_end(dctx, buf, buf_size); 130 if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { 131 *poutbuf = NULL; 132 *poutbuf_size = 0; 133 return buf_size; 134 } 135 } 136 *poutbuf = buf; 137 *poutbuf_size = buf_size; 138 return next; 139} 140 141const AVCodecParser ff_dnxhd_parser = { 142 .codec_ids = { AV_CODEC_ID_DNXHD }, 143 .priv_data_size = sizeof(DNXHDParserContext), 144 .parser_parse = dnxhd_parse, 145 .parser_close = ff_parse_close, 146}; 147