Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
/*
2
 * VC-1 and WMV3 parser
3
 * Copyright (c) 2006-2007 Konstantin Shishkov
4
 * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, Michael Niedermayer
5
 *
6
 * This file is part of FFmpeg.
7
 *
8
 * FFmpeg is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * FFmpeg is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with FFmpeg; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
 */
22
 
23
/**
24
 * @file
25
 * VC-1 and WMV3 parser
26
 */
27
 
28
#include "libavutil/attributes.h"
29
#include "parser.h"
30
#include "vc1.h"
31
#include "get_bits.h"
32
 
33
typedef struct {
34
    ParseContext pc;
35
    VC1Context v;
36
} VC1ParseContext;
37
 
38
static void vc1_extract_headers(AVCodecParserContext *s, AVCodecContext *avctx,
39
                                const uint8_t *buf, int buf_size)
40
{
41
    VC1ParseContext *vpc = s->priv_data;
42
    GetBitContext gb;
43
    const uint8_t *start, *end, *next;
44
    uint8_t *buf2 = av_mallocz(buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
45
 
46
    vpc->v.s.avctx = avctx;
47
    vpc->v.parse_only = 1;
48
    vpc->v.first_pic_header_flag = 1;
49
    next = buf;
50
    s->repeat_pict = 0;
51
 
52
    for(start = buf, end = buf + buf_size; next < end; start = next){
53
        int buf2_size, size;
54
        int ret;
55
 
56
        next = find_next_marker(start + 4, end);
57
        size = next - start - 4;
58
        buf2_size = vc1_unescape_buffer(start + 4, size, buf2);
59
        init_get_bits(&gb, buf2, buf2_size * 8);
60
        if(size <= 0) continue;
61
        switch(AV_RB32(start)){
62
        case VC1_CODE_SEQHDR:
63
            ff_vc1_decode_sequence_header(avctx, &vpc->v, &gb);
64
            break;
65
        case VC1_CODE_ENTRYPOINT:
66
            ff_vc1_decode_entry_point(avctx, &vpc->v, &gb);
67
            break;
68
        case VC1_CODE_FRAME:
69
            if(vpc->v.profile < PROFILE_ADVANCED)
70
                ret = ff_vc1_parse_frame_header    (&vpc->v, &gb);
71
            else
72
                ret = ff_vc1_parse_frame_header_adv(&vpc->v, &gb);
73
 
74
            if (ret < 0)
75
                break;
76
 
77
            /* keep AV_PICTURE_TYPE_BI internal to VC1 */
78
            if (vpc->v.s.pict_type == AV_PICTURE_TYPE_BI)
79
                s->pict_type = AV_PICTURE_TYPE_B;
80
            else
81
                s->pict_type = vpc->v.s.pict_type;
82
 
83
            if (avctx->ticks_per_frame > 1){
84
                // process pulldown flags
85
                s->repeat_pict = 1;
86
                // Pulldown flags are only valid when 'broadcast' has been set.
87
                // So ticks_per_frame will be 2
88
                if (vpc->v.rff){
89
                    // repeat field
90
                    s->repeat_pict = 2;
91
                }else if (vpc->v.rptfrm){
92
                    // repeat frames
93
                    s->repeat_pict = vpc->v.rptfrm * 2 + 1;
94
                }
95
            }
96
 
97
            if (vpc->v.broadcast && vpc->v.interlace && !vpc->v.psf)
98
                s->field_order = vpc->v.tff ? AV_FIELD_TT : AV_FIELD_BB;
99
            else
100
                s->field_order = AV_FIELD_PROGRESSIVE;
101
 
102
            break;
103
        }
104
    }
105
 
106
    av_free(buf2);
107
}
108
 
109
/**
110
 * Find the end of the current frame in the bitstream.
111
 * @return the position of the first byte of the next frame, or -1
112
 */
113
static int vc1_find_frame_end(ParseContext *pc, const uint8_t *buf,
114
                               int buf_size) {
115
    int pic_found, i;
116
    uint32_t state;
117
 
118
    pic_found= pc->frame_start_found;
119
    state= pc->state;
120
 
121
    i=0;
122
    if(!pic_found){
123
        for(i=0; i
124
            state= (state<<8) | buf[i];
125
            if(state == VC1_CODE_FRAME || state == VC1_CODE_FIELD){
126
                i++;
127
                pic_found=1;
128
                break;
129
            }
130
        }
131
    }
132
 
133
    if(pic_found){
134
        /* EOF considered as end of frame */
135
        if (buf_size == 0)
136
            return 0;
137
        for(; i
138
            state= (state<<8) | buf[i];
139
            if(IS_MARKER(state) && state != VC1_CODE_FIELD && state != VC1_CODE_SLICE){
140
                pc->frame_start_found=0;
141
                pc->state=-1;
142
                return i-3;
143
            }
144
        }
145
    }
146
    pc->frame_start_found= pic_found;
147
    pc->state= state;
148
    return END_NOT_FOUND;
149
}
150
 
151
static int vc1_parse(AVCodecParserContext *s,
152
                           AVCodecContext *avctx,
153
                           const uint8_t **poutbuf, int *poutbuf_size,
154
                           const uint8_t *buf, int buf_size)
155
{
156
    VC1ParseContext *vpc = s->priv_data;
157
    int next;
158
 
159
    if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){
160
        next= buf_size;
161
    }else{
162
        next= vc1_find_frame_end(&vpc->pc, buf, buf_size);
163
 
164
        if (ff_combine_frame(&vpc->pc, next, &buf, &buf_size) < 0) {
165
            *poutbuf = NULL;
166
            *poutbuf_size = 0;
167
            return buf_size;
168
        }
169
    }
170
 
171
    vc1_extract_headers(s, avctx, buf, buf_size);
172
 
173
    *poutbuf = buf;
174
    *poutbuf_size = buf_size;
175
    return next;
176
}
177
 
178
static int vc1_split(AVCodecContext *avctx,
179
                           const uint8_t *buf, int buf_size)
180
{
181
    int i;
182
    uint32_t state= -1;
183
    int charged=0;
184
 
185
    for(i=0; i
186
        state= (state<<8) | buf[i];
187
        if(IS_MARKER(state)){
188
            if(state == VC1_CODE_SEQHDR || state == VC1_CODE_ENTRYPOINT){
189
                charged=1;
190
            }else if(charged){
191
                return i-3;
192
            }
193
        }
194
    }
195
    return 0;
196
}
197
 
198
static av_cold int vc1_parse_init(AVCodecParserContext *s)
199
{
200
    VC1ParseContext *vpc = s->priv_data;
201
    vpc->v.s.slice_context_count = 1;
202
    return ff_vc1_init_common(&vpc->v);
203
}
204
 
205
AVCodecParser ff_vc1_parser = {
206
    .codec_ids      = { AV_CODEC_ID_VC1 },
207
    .priv_data_size = sizeof(VC1ParseContext),
208
    .parser_init    = vc1_parse_init,
209
    .parser_parse   = vc1_parse,
210
    .parser_close   = ff_parse_close,
211
    .split          = vc1_split,
212
};