1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * VC-1 and WMV3 parser
3cabdff1aSopenharmony_ci * Copyright (c) 2006-2007 Konstantin Shishkov
4cabdff1aSopenharmony_ci * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, Michael Niedermayer
5cabdff1aSopenharmony_ci *
6cabdff1aSopenharmony_ci * This file is part of FFmpeg.
7cabdff1aSopenharmony_ci *
8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
12cabdff1aSopenharmony_ci *
13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16cabdff1aSopenharmony_ci * Lesser General Public License for more details.
17cabdff1aSopenharmony_ci *
18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21cabdff1aSopenharmony_ci */
22cabdff1aSopenharmony_ci
23cabdff1aSopenharmony_ci/**
24cabdff1aSopenharmony_ci * @file
25cabdff1aSopenharmony_ci * VC-1 and WMV3 parser
26cabdff1aSopenharmony_ci */
27cabdff1aSopenharmony_ci
28cabdff1aSopenharmony_ci#include "libavutil/attributes.h"
29cabdff1aSopenharmony_ci#include "parser.h"
30cabdff1aSopenharmony_ci#include "vc1.h"
31cabdff1aSopenharmony_ci#include "get_bits.h"
32cabdff1aSopenharmony_ci
33cabdff1aSopenharmony_ci/** The maximum number of bytes of a sequence, entry point or
34cabdff1aSopenharmony_ci *  frame header whose values we pay any attention to */
35cabdff1aSopenharmony_ci#define UNESCAPED_THRESHOLD 37
36cabdff1aSopenharmony_ci
37cabdff1aSopenharmony_ci/** The maximum number of bytes of a sequence, entry point or
38cabdff1aSopenharmony_ci *  frame header which must be valid memory (because they are
39cabdff1aSopenharmony_ci *  used to update the bitstream cache in skip_bits() calls)
40cabdff1aSopenharmony_ci */
41cabdff1aSopenharmony_ci#define UNESCAPED_LIMIT 144
42cabdff1aSopenharmony_ci
43cabdff1aSopenharmony_citypedef enum {
44cabdff1aSopenharmony_ci    NO_MATCH,
45cabdff1aSopenharmony_ci    ONE_ZERO,
46cabdff1aSopenharmony_ci    TWO_ZEROS,
47cabdff1aSopenharmony_ci    ONE
48cabdff1aSopenharmony_ci} VC1ParseSearchState;
49cabdff1aSopenharmony_ci
50cabdff1aSopenharmony_citypedef struct VC1ParseContext {
51cabdff1aSopenharmony_ci    ParseContext pc;
52cabdff1aSopenharmony_ci    VC1Context v;
53cabdff1aSopenharmony_ci    uint8_t prev_start_code;
54cabdff1aSopenharmony_ci    size_t bytes_to_skip;
55cabdff1aSopenharmony_ci    uint8_t unesc_buffer[UNESCAPED_LIMIT];
56cabdff1aSopenharmony_ci    size_t unesc_index;
57cabdff1aSopenharmony_ci    VC1ParseSearchState search_state;
58cabdff1aSopenharmony_ci} VC1ParseContext;
59cabdff1aSopenharmony_ci
60cabdff1aSopenharmony_cistatic void vc1_extract_header(AVCodecParserContext *s, AVCodecContext *avctx,
61cabdff1aSopenharmony_ci                               const uint8_t *buf, int buf_size)
62cabdff1aSopenharmony_ci{
63cabdff1aSopenharmony_ci    /* Parse the header we just finished unescaping */
64cabdff1aSopenharmony_ci    VC1ParseContext *vpc = s->priv_data;
65cabdff1aSopenharmony_ci    GetBitContext gb;
66cabdff1aSopenharmony_ci    int ret;
67cabdff1aSopenharmony_ci    vpc->v.s.avctx = avctx;
68cabdff1aSopenharmony_ci    vpc->v.parse_only = 1;
69cabdff1aSopenharmony_ci    init_get_bits8(&gb, buf, buf_size);
70cabdff1aSopenharmony_ci    switch (vpc->prev_start_code) {
71cabdff1aSopenharmony_ci    case VC1_CODE_SEQHDR & 0xFF:
72cabdff1aSopenharmony_ci        ff_vc1_decode_sequence_header(avctx, &vpc->v, &gb);
73cabdff1aSopenharmony_ci        break;
74cabdff1aSopenharmony_ci    case VC1_CODE_ENTRYPOINT & 0xFF:
75cabdff1aSopenharmony_ci        ff_vc1_decode_entry_point(avctx, &vpc->v, &gb);
76cabdff1aSopenharmony_ci        break;
77cabdff1aSopenharmony_ci    case VC1_CODE_FRAME & 0xFF:
78cabdff1aSopenharmony_ci        if(vpc->v.profile < PROFILE_ADVANCED)
79cabdff1aSopenharmony_ci            ret = ff_vc1_parse_frame_header    (&vpc->v, &gb);
80cabdff1aSopenharmony_ci        else
81cabdff1aSopenharmony_ci            ret = ff_vc1_parse_frame_header_adv(&vpc->v, &gb);
82cabdff1aSopenharmony_ci
83cabdff1aSopenharmony_ci        if (ret < 0)
84cabdff1aSopenharmony_ci            break;
85cabdff1aSopenharmony_ci
86cabdff1aSopenharmony_ci        /* keep AV_PICTURE_TYPE_BI internal to VC1 */
87cabdff1aSopenharmony_ci        if (vpc->v.s.pict_type == AV_PICTURE_TYPE_BI)
88cabdff1aSopenharmony_ci            s->pict_type = AV_PICTURE_TYPE_B;
89cabdff1aSopenharmony_ci        else
90cabdff1aSopenharmony_ci            s->pict_type = vpc->v.s.pict_type;
91cabdff1aSopenharmony_ci
92cabdff1aSopenharmony_ci        if (avctx->ticks_per_frame > 1){
93cabdff1aSopenharmony_ci            // process pulldown flags
94cabdff1aSopenharmony_ci            s->repeat_pict = 1;
95cabdff1aSopenharmony_ci            // Pulldown flags are only valid when 'broadcast' has been set.
96cabdff1aSopenharmony_ci            // So ticks_per_frame will be 2
97cabdff1aSopenharmony_ci            if (vpc->v.rff){
98cabdff1aSopenharmony_ci                // repeat field
99cabdff1aSopenharmony_ci                s->repeat_pict = 2;
100cabdff1aSopenharmony_ci            }else if (vpc->v.rptfrm){
101cabdff1aSopenharmony_ci                // repeat frames
102cabdff1aSopenharmony_ci                s->repeat_pict = vpc->v.rptfrm * 2 + 1;
103cabdff1aSopenharmony_ci            }
104cabdff1aSopenharmony_ci        }else{
105cabdff1aSopenharmony_ci            s->repeat_pict = 0;
106cabdff1aSopenharmony_ci        }
107cabdff1aSopenharmony_ci
108cabdff1aSopenharmony_ci        if (vpc->v.broadcast && vpc->v.interlace && !vpc->v.psf)
109cabdff1aSopenharmony_ci            s->field_order = vpc->v.tff ? AV_FIELD_TT : AV_FIELD_BB;
110cabdff1aSopenharmony_ci        else
111cabdff1aSopenharmony_ci            s->field_order = AV_FIELD_PROGRESSIVE;
112cabdff1aSopenharmony_ci
113cabdff1aSopenharmony_ci        break;
114cabdff1aSopenharmony_ci    }
115cabdff1aSopenharmony_ci    if (avctx->framerate.num)
116cabdff1aSopenharmony_ci        avctx->time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){avctx->ticks_per_frame, 1}));
117cabdff1aSopenharmony_ci    s->format = vpc->v.chromaformat == 1 ? AV_PIX_FMT_YUV420P
118cabdff1aSopenharmony_ci                                         : AV_PIX_FMT_NONE;
119cabdff1aSopenharmony_ci    if (avctx->width && avctx->height) {
120cabdff1aSopenharmony_ci        s->width        = avctx->width;
121cabdff1aSopenharmony_ci        s->height       = avctx->height;
122cabdff1aSopenharmony_ci        s->coded_width  = FFALIGN(avctx->coded_width,  16);
123cabdff1aSopenharmony_ci        s->coded_height = FFALIGN(avctx->coded_height, 16);
124cabdff1aSopenharmony_ci    }
125cabdff1aSopenharmony_ci}
126cabdff1aSopenharmony_ci
127cabdff1aSopenharmony_cistatic int vc1_parse(AVCodecParserContext *s,
128cabdff1aSopenharmony_ci                           AVCodecContext *avctx,
129cabdff1aSopenharmony_ci                           const uint8_t **poutbuf, int *poutbuf_size,
130cabdff1aSopenharmony_ci                           const uint8_t *buf, int buf_size)
131cabdff1aSopenharmony_ci{
132cabdff1aSopenharmony_ci    /* Here we do the searching for frame boundaries and headers at
133cabdff1aSopenharmony_ci     * the same time. Only a minimal amount at the start of each
134cabdff1aSopenharmony_ci     * header is unescaped. */
135cabdff1aSopenharmony_ci    VC1ParseContext *vpc = s->priv_data;
136cabdff1aSopenharmony_ci    int pic_found = vpc->pc.frame_start_found;
137cabdff1aSopenharmony_ci    uint8_t *unesc_buffer = vpc->unesc_buffer;
138cabdff1aSopenharmony_ci    size_t unesc_index = vpc->unesc_index;
139cabdff1aSopenharmony_ci    VC1ParseSearchState search_state = vpc->search_state;
140cabdff1aSopenharmony_ci    int start_code_found = 0;
141cabdff1aSopenharmony_ci    int next = END_NOT_FOUND;
142cabdff1aSopenharmony_ci    int i = vpc->bytes_to_skip;
143cabdff1aSopenharmony_ci
144cabdff1aSopenharmony_ci    if (pic_found && buf_size == 0) {
145cabdff1aSopenharmony_ci        /* EOF considered as end of frame */
146cabdff1aSopenharmony_ci        memset(unesc_buffer + unesc_index, 0, UNESCAPED_THRESHOLD - unesc_index);
147cabdff1aSopenharmony_ci        vc1_extract_header(s, avctx, unesc_buffer, unesc_index);
148cabdff1aSopenharmony_ci        next = 0;
149cabdff1aSopenharmony_ci    }
150cabdff1aSopenharmony_ci    while (i < buf_size) {
151cabdff1aSopenharmony_ci        uint8_t b;
152cabdff1aSopenharmony_ci        start_code_found = 0;
153cabdff1aSopenharmony_ci        while (i < buf_size && unesc_index < UNESCAPED_THRESHOLD) {
154cabdff1aSopenharmony_ci            b = buf[i++];
155cabdff1aSopenharmony_ci            unesc_buffer[unesc_index++] = b;
156cabdff1aSopenharmony_ci            if (search_state <= ONE_ZERO)
157cabdff1aSopenharmony_ci                search_state = b ? NO_MATCH : search_state + 1;
158cabdff1aSopenharmony_ci            else if (search_state == TWO_ZEROS) {
159cabdff1aSopenharmony_ci                if (b == 1)
160cabdff1aSopenharmony_ci                    search_state = ONE;
161cabdff1aSopenharmony_ci                else if (b > 1) {
162cabdff1aSopenharmony_ci                    if (b == 3)
163cabdff1aSopenharmony_ci                        unesc_index--; // swallow emulation prevention byte
164cabdff1aSopenharmony_ci                    search_state = NO_MATCH;
165cabdff1aSopenharmony_ci                }
166cabdff1aSopenharmony_ci            }
167cabdff1aSopenharmony_ci            else { // search_state == ONE
168cabdff1aSopenharmony_ci                // Header unescaping terminates early due to detection of next start code
169cabdff1aSopenharmony_ci                search_state = NO_MATCH;
170cabdff1aSopenharmony_ci                start_code_found = 1;
171cabdff1aSopenharmony_ci                break;
172cabdff1aSopenharmony_ci            }
173cabdff1aSopenharmony_ci        }
174cabdff1aSopenharmony_ci        if ((s->flags & PARSER_FLAG_COMPLETE_FRAMES) &&
175cabdff1aSopenharmony_ci                unesc_index >= UNESCAPED_THRESHOLD &&
176cabdff1aSopenharmony_ci                vpc->prev_start_code == (VC1_CODE_FRAME & 0xFF))
177cabdff1aSopenharmony_ci        {
178cabdff1aSopenharmony_ci            // No need to keep scanning the rest of the buffer for
179cabdff1aSopenharmony_ci            // start codes if we know it contains a complete frame and
180cabdff1aSopenharmony_ci            // we've already unescaped all we need of the frame header
181cabdff1aSopenharmony_ci            vc1_extract_header(s, avctx, unesc_buffer, unesc_index);
182cabdff1aSopenharmony_ci            break;
183cabdff1aSopenharmony_ci        }
184cabdff1aSopenharmony_ci        if (unesc_index >= UNESCAPED_THRESHOLD && !start_code_found) {
185cabdff1aSopenharmony_ci            while (i < buf_size) {
186cabdff1aSopenharmony_ci                if (search_state == NO_MATCH) {
187cabdff1aSopenharmony_ci                    i += vpc->v.vc1dsp.startcode_find_candidate(buf + i, buf_size - i);
188cabdff1aSopenharmony_ci                    if (i < buf_size) {
189cabdff1aSopenharmony_ci                        search_state = ONE_ZERO;
190cabdff1aSopenharmony_ci                    }
191cabdff1aSopenharmony_ci                    i++;
192cabdff1aSopenharmony_ci                } else {
193cabdff1aSopenharmony_ci                    b = buf[i++];
194cabdff1aSopenharmony_ci                    if (search_state == ONE_ZERO)
195cabdff1aSopenharmony_ci                        search_state = b ? NO_MATCH : TWO_ZEROS;
196cabdff1aSopenharmony_ci                    else if (search_state == TWO_ZEROS) {
197cabdff1aSopenharmony_ci                        if (b >= 1)
198cabdff1aSopenharmony_ci                            search_state = b == 1 ? ONE : NO_MATCH;
199cabdff1aSopenharmony_ci                    }
200cabdff1aSopenharmony_ci                    else { // search_state == ONE
201cabdff1aSopenharmony_ci                        search_state = NO_MATCH;
202cabdff1aSopenharmony_ci                        start_code_found = 1;
203cabdff1aSopenharmony_ci                        break;
204cabdff1aSopenharmony_ci                    }
205cabdff1aSopenharmony_ci                }
206cabdff1aSopenharmony_ci            }
207cabdff1aSopenharmony_ci        }
208cabdff1aSopenharmony_ci        if (start_code_found) {
209cabdff1aSopenharmony_ci            vc1_extract_header(s, avctx, unesc_buffer, unesc_index);
210cabdff1aSopenharmony_ci
211cabdff1aSopenharmony_ci            vpc->prev_start_code = b;
212cabdff1aSopenharmony_ci            unesc_index = 0;
213cabdff1aSopenharmony_ci
214cabdff1aSopenharmony_ci            if (!(s->flags & PARSER_FLAG_COMPLETE_FRAMES)) {
215cabdff1aSopenharmony_ci                if (!pic_found && (b == (VC1_CODE_FRAME & 0xFF) || b == (VC1_CODE_FIELD & 0xFF))) {
216cabdff1aSopenharmony_ci                    pic_found = 1;
217cabdff1aSopenharmony_ci                }
218cabdff1aSopenharmony_ci                else if (pic_found && b != (VC1_CODE_FIELD & 0xFF) && b != (VC1_CODE_SLICE & 0xFF)) {
219cabdff1aSopenharmony_ci                    next = i - 4;
220cabdff1aSopenharmony_ci                    pic_found = b == (VC1_CODE_FRAME & 0xFF);
221cabdff1aSopenharmony_ci                    break;
222cabdff1aSopenharmony_ci                }
223cabdff1aSopenharmony_ci            }
224cabdff1aSopenharmony_ci        }
225cabdff1aSopenharmony_ci    }
226cabdff1aSopenharmony_ci
227cabdff1aSopenharmony_ci    vpc->pc.frame_start_found = pic_found;
228cabdff1aSopenharmony_ci    vpc->unesc_index = unesc_index;
229cabdff1aSopenharmony_ci    vpc->search_state = search_state;
230cabdff1aSopenharmony_ci
231cabdff1aSopenharmony_ci    if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
232cabdff1aSopenharmony_ci        next = buf_size;
233cabdff1aSopenharmony_ci    } else {
234cabdff1aSopenharmony_ci        if (ff_combine_frame(&vpc->pc, next, &buf, &buf_size) < 0) {
235cabdff1aSopenharmony_ci            vpc->bytes_to_skip = 0;
236cabdff1aSopenharmony_ci            *poutbuf = NULL;
237cabdff1aSopenharmony_ci            *poutbuf_size = 0;
238cabdff1aSopenharmony_ci            return buf_size;
239cabdff1aSopenharmony_ci        }
240cabdff1aSopenharmony_ci    }
241cabdff1aSopenharmony_ci
242cabdff1aSopenharmony_ci    /* If we return with a valid pointer to a combined frame buffer
243cabdff1aSopenharmony_ci     * then on the next call then we'll have been unhelpfully rewound
244cabdff1aSopenharmony_ci     * by up to 4 bytes (depending upon whether the start code
245cabdff1aSopenharmony_ci     * overlapped the input buffer, and if so by how much). We don't
246cabdff1aSopenharmony_ci     * want this: it will either cause spurious second detections of
247cabdff1aSopenharmony_ci     * the start code we've already seen, or cause extra bytes to be
248cabdff1aSopenharmony_ci     * inserted at the start of the unescaped buffer. */
249cabdff1aSopenharmony_ci    vpc->bytes_to_skip = 4;
250cabdff1aSopenharmony_ci    if (next < 0 && next != END_NOT_FOUND)
251cabdff1aSopenharmony_ci        vpc->bytes_to_skip += next;
252cabdff1aSopenharmony_ci
253cabdff1aSopenharmony_ci    *poutbuf = buf;
254cabdff1aSopenharmony_ci    *poutbuf_size = buf_size;
255cabdff1aSopenharmony_ci    return next;
256cabdff1aSopenharmony_ci}
257cabdff1aSopenharmony_ci
258cabdff1aSopenharmony_cistatic av_cold int vc1_parse_init(AVCodecParserContext *s)
259cabdff1aSopenharmony_ci{
260cabdff1aSopenharmony_ci    VC1ParseContext *vpc = s->priv_data;
261cabdff1aSopenharmony_ci    vpc->v.s.slice_context_count = 1;
262cabdff1aSopenharmony_ci    vpc->v.first_pic_header_flag = 1;
263cabdff1aSopenharmony_ci    vpc->prev_start_code = 0;
264cabdff1aSopenharmony_ci    vpc->bytes_to_skip = 0;
265cabdff1aSopenharmony_ci    vpc->unesc_index = 0;
266cabdff1aSopenharmony_ci    vpc->search_state = NO_MATCH;
267cabdff1aSopenharmony_ci    ff_vc1_init_common(&vpc->v);
268cabdff1aSopenharmony_ci    return 0;
269cabdff1aSopenharmony_ci}
270cabdff1aSopenharmony_ci
271cabdff1aSopenharmony_ciconst AVCodecParser ff_vc1_parser = {
272cabdff1aSopenharmony_ci    .codec_ids      = { AV_CODEC_ID_VC1 },
273cabdff1aSopenharmony_ci    .priv_data_size = sizeof(VC1ParseContext),
274cabdff1aSopenharmony_ci    .parser_init    = vc1_parse_init,
275cabdff1aSopenharmony_ci    .parser_parse   = vc1_parse,
276cabdff1aSopenharmony_ci    .parser_close   = ff_parse_close,
277cabdff1aSopenharmony_ci};
278