avformat/rawdec: Make the raw packet size configurable
[ffmpeg.git] / libavcodec / dnxhd_parser.c
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
30 typedef struct {
31     ParseContext pc;
32     int cur_byte;
33     int remaining;
34     int w, h;
35 } DNXHDParserContext;
36
37 static 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 = avpriv_dnxhd_get_frame_size(cid);
77                 if (remaining <= 0) {
78                     remaining = avpriv_dnxhd_get_hr_frame_size(cid, dctx->w, dctx->h);
79                     if (remaining <= 0)
80                         continue;
81                 }
82                 dctx->remaining = remaining;
83                 if (buf_size - i + 47 >= dctx->remaining) {
84                     pc->frame_start_found = 0;
85                     pc->state64 = -1;
86                     dctx->cur_byte = 0;
87                     dctx->remaining = 0;
88                     return remaining;
89                 } else {
90                     dctx->remaining -= buf_size;
91                     // Update variables for correctness, they are currently not used beyond here
92                     state = -1;
93                     dctx->cur_byte += buf_size - i;
94                     break;
95                 }
96             }
97         }
98     } else if (pic_found) {
99         if (dctx->remaining > buf_size) {
100             dctx->remaining -= buf_size;
101         } else {
102             int remaining = dctx->remaining;
103
104             pc->frame_start_found = 0;
105             pc->state64 = -1;
106             dctx->cur_byte = 0;
107             dctx->remaining = 0;
108             return remaining;
109         }
110     }
111     pc->frame_start_found = pic_found;
112     pc->state64 = state;
113     return END_NOT_FOUND;
114 }
115
116 static int dnxhd_parse(AVCodecParserContext *s,
117                        AVCodecContext *avctx,
118                        const uint8_t **poutbuf, int *poutbuf_size,
119                        const uint8_t *buf, int buf_size)
120 {
121     DNXHDParserContext *dctx = s->priv_data;
122     ParseContext *pc = &dctx->pc;
123     int next;
124
125     if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
126         next = buf_size;
127     } else {
128         next = dnxhd_find_frame_end(dctx, buf, buf_size);
129         if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
130             *poutbuf      = NULL;
131             *poutbuf_size = 0;
132             return buf_size;
133         }
134     }
135     *poutbuf      = buf;
136     *poutbuf_size = buf_size;
137     return next;
138 }
139
140 AVCodecParser ff_dnxhd_parser = {
141     .codec_ids      = { AV_CODEC_ID_DNXHD },
142     .priv_data_size = sizeof(DNXHDParserContext),
143     .parser_parse   = dnxhd_parse,
144     .parser_close   = ff_parse_close,
145 };