]> git.sesse.net Git - ffmpeg/blob - libavcodec/dnxhd_parser.c
Merge commit 'f89ec87afaf0d1abb6d450253b0b348fd554533b'
[ffmpeg] / 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                     int remaining = dctx->remaining;
85
86                     pc->frame_start_found = 0;
87                     pc->state64 = -1;
88                     dctx->cur_byte = 0;
89                     dctx->remaining = 0;
90                     return remaining;
91                 } else {
92                     dctx->remaining -= buf_size;
93                 }
94             }
95         }
96     } else if (pic_found) {
97         if (dctx->remaining > buf_size) {
98             dctx->remaining -= buf_size;
99         } else {
100             int remaining = dctx->remaining;
101
102             pc->frame_start_found = 0;
103             pc->state64 = -1;
104             dctx->cur_byte = 0;
105             dctx->remaining = 0;
106             return remaining;
107         }
108     }
109     pc->frame_start_found = pic_found;
110     pc->state64 = state;
111     return END_NOT_FOUND;
112 }
113
114 static int dnxhd_parse(AVCodecParserContext *s,
115                        AVCodecContext *avctx,
116                        const uint8_t **poutbuf, int *poutbuf_size,
117                        const uint8_t *buf, int buf_size)
118 {
119     DNXHDParserContext *dctx = s->priv_data;
120     ParseContext *pc = &dctx->pc;
121     int next;
122
123     if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
124         next = buf_size;
125     } else {
126         next = dnxhd_find_frame_end(dctx, buf, buf_size);
127         if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
128             *poutbuf      = NULL;
129             *poutbuf_size = 0;
130             return buf_size;
131         }
132     }
133     *poutbuf      = buf;
134     *poutbuf_size = buf_size;
135     return next;
136 }
137
138 AVCodecParser ff_dnxhd_parser = {
139     .codec_ids      = { AV_CODEC_ID_DNXHD },
140     .priv_data_size = sizeof(DNXHDParserContext),
141     .parser_parse   = dnxhd_parse,
142     .parser_close   = ff_parse_close,
143 };