viddec_vc1_parse.c revision bd8388b4555645b3d29abc6a94c303638064d69a
1#include "viddec_fw_debug.h"    // For DEB
2#include "viddec_parser_ops.h"  // For parser helper functions
3#include "vc1.h"                // For the parser structure
4#include "vc1parse.h"           // For vc1 parser helper functions
5#ifdef VBP
6#include "viddec_pm.h"
7#endif
8#define vc1_is_frame_start_code( ch )                                   \
9    (( vc1_SCField == ch ||vc1_SCSlice == ch || vc1_SCFrameHeader == ch ) ? 1 : 0)
10
11/* init function */
12#ifdef VBP
13void viddec_vc1_init(void *ctxt, uint32_t *persist_mem, uint32_t preserve)
14#else
15static void viddec_vc1_init(void *ctxt, uint32_t *persist_mem, uint32_t preserve)
16#endif
17{
18    vc1_viddec_parser_t *parser = ctxt;
19    int i;
20
21    persist_mem = persist_mem;
22
23    for(i=0; i<VC1_NUM_REFERENCE_FRAMES; i++)
24    {
25        parser->ref_frame[i].id   = -1; /* first I frame checks that value */
26        parser->ref_frame[i].anchor[0] = 1;
27        parser->ref_frame[i].anchor[1] = 1;
28        parser->ref_frame[i].intcomp_top = 0;
29        parser->ref_frame[i].intcomp_bot = 0;
30    }
31
32    parser->intcomp_top[0] = 0;
33    parser->intcomp_bot[0] = 0;
34    parser->intcomp_top[1] = 0;
35    parser->intcomp_bot[1] = 0;
36    parser->is_reference_picture = false;
37
38    memset(&parser->info.picLayerHeader, 0, sizeof(vc1_PictureLayerHeader));
39
40    if(preserve)
41    {
42        parser->sc_seen &= VC1_EP_MASK;
43        parser->sc_seen_since_last_wkld &= VC1_EP_MASK;
44    }
45    else
46    {
47        parser->sc_seen = VC1_SC_INVALID;
48        parser->sc_seen_since_last_wkld = VC1_SC_INVALID;
49        memset(&parser->info.metadata, 0, sizeof(parser->info.metadata));
50    }
51
52    return;
53} // viddec_vc1_init
54
55static void vc1_swap_intcomp(vc1_viddec_parser_t *parser)
56{
57    parser->intcomp_top[1] = parser->intcomp_top[0];
58    parser->intcomp_bot[1] = parser->intcomp_bot[0];
59    parser->intcomp_top[0] = 0;
60    parser->intcomp_bot[0] = 0;
61
62    return;
63} // vc1_swap_intcomp
64
65#ifdef VBP
66uint32_t viddec_vc1_parse(void *parent, void *ctxt)
67#else
68static uint32_t viddec_vc1_parse(void *parent, void *ctxt)
69#endif
70{
71    vc1_viddec_parser_t *parser = ctxt;
72    uint32_t sc=0x0;
73    int32_t ret=0, status=0;
74
75#ifdef VBP
76    /* This works only if there is one slice and no start codes */
77    /* A better fix would be to insert start codes it there aren't any. */
78    ret = viddec_pm_peek_bits(parent, &sc, 32);
79    if ((sc > 0x0100) && (sc < 0x0200)) /* a Start code will be in this range. */
80    {
81      ret = viddec_pm_get_bits(parent, &sc, 32);
82    }
83    else
84    {
85      /* In cases where we get a buffer with no start codes, we assume */
86      /* that this is a frame of data. We may have to fix this later. */
87      sc = vc1_SCFrameHeader;
88    }
89#else
90    ret = viddec_pm_get_bits(parent, &sc, 32);
91#endif
92    sc = sc & 0xFF;
93    parser->is_frame_start = (sc == vc1_SCFrameHeader);
94    DEB("START_CODE = %02x\n", sc);
95    switch( sc )
96    {
97        case vc1_SCSequenceHeader:
98        {
99            uint32_t data=0;
100            parser->ref_frame[0].anchor[0] = 1;
101            parser->ref_frame[0].anchor[1] = 1;
102            parser->ref_frame[1].anchor[0] = 1;
103            parser->ref_frame[1].anchor[1] = 1;
104            memset( &parser->info.metadata, 0, sizeof(parser->info.metadata));
105            /* look if we have a rcv header for main or simple profile */
106            ret = viddec_pm_peek_bits(parent,&data ,2);
107
108            if (data == 3)
109            {
110                status = vc1_ParseSequenceLayer(parent, &parser->info);
111            }
112            else
113            {
114                status = vc1_ParseRCVSequenceLayer(parent, &parser->info);
115            }
116            parser->sc_seen = VC1_SC_SEQ;
117            parser->sc_seen_since_last_wkld |= VC1_SC_SEQ;
118#ifdef VBP
119			parser->start_code = VC1_SC_SEQ;
120#endif
121            break;
122        }
123
124        case vc1_SCEntryPointHeader:
125        {
126            status = vc1_ParseEntryPointLayer(parent, &parser->info);
127            parser->sc_seen |= VC1_SC_EP;
128            // Clear all bits indicating data below ep header
129            parser->sc_seen &= VC1_EP_MASK;
130            parser->sc_seen_since_last_wkld |= VC1_SC_EP;
131#ifdef VBP
132			parser->start_code = VC1_SC_EP;
133#endif
134			break;
135        }
136
137        case vc1_SCFrameHeader:
138        {
139            memset(&parser->info.picLayerHeader, 0, sizeof(vc1_PictureLayerHeader));
140            status = vc1_ParsePictureLayer(parent, &parser->info);
141            if((parser->info.picLayerHeader.PTypeField1 == VC1_I_FRAME) ||
142               (parser->info.picLayerHeader.PTypeField1 == VC1_P_FRAME) ||
143               (parser->info.picLayerHeader.PTYPE == VC1_I_FRAME) ||
144               (parser->info.picLayerHeader.PTYPE == VC1_P_FRAME))
145            {
146                vc1_swap_intcomp(parser);
147            }
148            parser->sc_seen |= VC1_SC_FRM;
149            // Clear all bits indicating data below frm header
150            parser->sc_seen &= VC1_FRM_MASK;
151            parser->sc_seen_since_last_wkld |= VC1_SC_FRM;
152            vc1_start_new_frame ( parent, parser );
153#ifdef VBP
154			parser->start_code = VC1_SC_FRM;
155#endif
156			break;
157        }
158
159        case vc1_SCSlice:
160        {
161            status = vc1_ParseSliceLayer(parent, &parser->info);
162            parser->sc_seen_since_last_wkld |= VC1_SC_SLC;
163#ifdef VBP
164         	parser->start_code = VC1_SC_SLC;
165#endif
166            break;
167        }
168
169        case vc1_SCField:
170        {
171            parser->info.picLayerHeader.SLICE_ADDR = 0;
172            parser->info.picLayerHeader.CurrField = 1;
173            parser->info.picLayerHeader.REFFIELD = 0;
174            parser->info.picLayerHeader.NUMREF = 0;
175            parser->info.picLayerHeader.MBMODETAB = 0;
176            parser->info.picLayerHeader.MV4SWITCH = 0;
177            parser->info.picLayerHeader.DMVRANGE = 0;
178            parser->info.picLayerHeader.MVTAB = 0;
179            parser->info.picLayerHeader.MVMODE = 0;
180            parser->info.picLayerHeader.MVRANGE = 0;
181#ifdef VBP
182			parser->info.picLayerHeader.raw_MVTYPEMB = 0;
183			parser->info.picLayerHeader.raw_DIRECTMB = 0;
184			parser->info.picLayerHeader.raw_SKIPMB = 0;
185			parser->info.picLayerHeader.raw_ACPRED = 0;
186			parser->info.picLayerHeader.raw_FIELDTX = 0;
187			parser->info.picLayerHeader.raw_OVERFLAGS = 0;
188			parser->info.picLayerHeader.raw_FORWARDMB = 0;
189
190			memset(&(parser->info.picLayerHeader.MVTYPEMB), 0, sizeof(vc1_Bitplane));
191			memset(&(parser->info.picLayerHeader.DIRECTMB), 0, sizeof(vc1_Bitplane));
192			memset(&(parser->info.picLayerHeader.SKIPMB), 0, sizeof(vc1_Bitplane));
193			memset(&(parser->info.picLayerHeader.ACPRED), 0, sizeof(vc1_Bitplane));
194			memset(&(parser->info.picLayerHeader.FIELDTX), 0, sizeof(vc1_Bitplane));
195			memset(&(parser->info.picLayerHeader.OVERFLAGS), 0, sizeof(vc1_Bitplane));
196			memset(&(parser->info.picLayerHeader.FORWARDMB), 0, sizeof(vc1_Bitplane));
197
198			parser->info.picLayerHeader.ALTPQUANT = 0;
199			parser->info.picLayerHeader.DQDBEDGE = 0;
200 #endif
201
202            status = vc1_ParseFieldLayer(parent, &parser->info);
203            if((parser->info.picLayerHeader.PTypeField2 == VC1_I_FRAME) ||
204               (parser->info.picLayerHeader.PTypeField2 == VC1_P_FRAME))
205            {
206                vc1_swap_intcomp(parser);
207            }
208
209            parser->sc_seen |= VC1_SC_FLD;
210            parser->sc_seen_since_last_wkld |= VC1_SC_FLD;
211#ifdef VBP
212			parser->start_code = VC1_SC_FLD;
213#endif
214            break;
215        }
216
217        case vc1_SCSequenceUser:
218        case vc1_SCEntryPointUser:
219        case vc1_SCFrameUser:
220        case vc1_SCSliceUser:
221        case vc1_SCFieldUser:
222        {/* Handle user data */
223            status = vc1_ParseAndAppendUserData(parent, sc); //parse and add items
224            parser->sc_seen_since_last_wkld |= VC1_SC_UD;
225#ifdef VBP
226            parser->start_code = VC1_SC_UD;
227#endif
228            break;
229        }
230
231        case vc1_SCEndOfSequence:
232        {
233            parser->sc_seen = VC1_SC_INVALID;
234            parser->sc_seen_since_last_wkld |= VC1_SC_INVALID;
235#ifdef VBP
236            parser->start_code = VC1_SC_INVALID;
237#endif
238            break;
239        }
240        default: /* Any other SC that is not handled */
241        {
242            DEB("SC = %02x - unhandled\n", sc );
243#ifdef VBP
244            parser->start_code = VC1_SC_INVALID;
245#endif
246            break;
247        }
248    }
249
250    if( vc1_is_frame_start_code( sc ) ) {
251        vc1_parse_emit_current_frame( parent, parser );
252    }
253
254    return VIDDEC_PARSE_SUCESS;
255} // viddec_vc1_parse
256
257/**
258   If a picture header was seen and the next start code is a sequence header, entrypoint header,
259   end of sequence or another frame header, this api returns frame done.
260   If a sequence header and a frame header was not seen before this point, all the
261   information needed for decode is not present and parser errors are reported.
262*/
263#ifdef VBP
264uint32_t viddec_vc1_wkld_done(void *parent, void *ctxt, unsigned int next_sc, uint32_t *codec_specific_errors)
265#else
266static uint32_t viddec_vc1_wkld_done(void *parent, void *ctxt, unsigned int next_sc, uint32_t *codec_specific_errors)
267#endif
268{
269    vc1_viddec_parser_t *parser = ctxt;
270    int ret = VIDDEC_PARSE_SUCESS;
271    parent = parent;
272    switch (next_sc)
273    {
274        case vc1_SCFrameHeader:
275            if(((parser->sc_seen_since_last_wkld & VC1_SC_EP) ||
276                (parser->sc_seen_since_last_wkld & VC1_SC_SEQ)) &&
277               (!(parser->sc_seen_since_last_wkld & VC1_SC_FRM)))
278            {
279                break;
280            }
281            // Deliberate fall-thru case
282        case vc1_SCEntryPointHeader:
283            if((next_sc == vc1_SCEntryPointHeader) &&
284               (parser->sc_seen_since_last_wkld & VC1_SC_SEQ) &&
285               (!(parser->sc_seen_since_last_wkld & VC1_SC_EP)))
286            {
287                break;
288            }
289            // Deliberate fall-thru case
290        case vc1_SCSequenceHeader:
291        case vc1_SCEndOfSequence:
292        case VIDDEC_PARSE_EOS:
293        case VIDDEC_PARSE_DISCONTINUITY:
294            ret = VIDDEC_PARSE_FRMDONE;
295            // Set errors for progressive
296            if((parser->sc_seen & VC1_SC_SEQ) && (parser->sc_seen & VC1_SC_FRM))
297                *codec_specific_errors = 0;
298            else
299                *codec_specific_errors |= VIDDEC_FW_WORKLOAD_ERR_NOTDECODABLE;
300            vc1_end_frame(parser);
301            parser->sc_seen_since_last_wkld = VC1_SC_INVALID;
302            // TODO: Need to check for interlaced
303            break;
304        default:
305            ret = VIDDEC_PARSE_SUCESS;
306            break;
307    } //switch
308    DEB("sc: 0x%x, sc_seen: 0x%x, sc_since_last_wkld:%d, error:%d, ret: %d\n",
309        next_sc, parser->sc_seen, parser->sc_seen_since_last_wkld,
310        *codec_specific_errors, ret);
311
312    return ret;
313} // viddec_vc1_wkld_done
314
315#ifdef VBP
316void viddec_vc1_get_context_size(viddec_parser_memory_sizes_t *size)
317#else
318static void viddec_vc1_get_context_size(viddec_parser_memory_sizes_t *size)
319#endif
320{
321    size->context_size = sizeof(vc1_viddec_parser_t);
322    size->persist_size = 0;
323    return;
324} // viddec_vc1_get_context_size
325
326#ifdef VBP
327uint32_t viddec_vc1_is_start_frame(void *ctxt)
328#else
329static uint32_t viddec_vc1_is_start_frame(void *ctxt)
330#endif
331{
332    vc1_viddec_parser_t *parser = (vc1_viddec_parser_t *) ctxt;
333    return parser->is_frame_start;
334} // viddec_vc1_is_start_frame
335
336void viddec_vc1_get_ops(viddec_parser_ops_t *ops)
337{
338    ops->init = viddec_vc1_init;
339    ops->parse_syntax = viddec_vc1_parse;
340    ops->get_cxt_size = viddec_vc1_get_context_size;
341    ops->is_wkld_done = viddec_vc1_wkld_done;
342    ops->is_frame_start = viddec_vc1_is_start_frame;
343    return;
344} // viddec_vc1_get_ops
345
346