1#include "viddec_fw_workload.h"
2#include "viddec_parser_ops.h"
3#include "viddec_fw_mp4.h"
4#include "viddec_mp4_parse.h"
5
6uint32_t viddec_fw_mp4_populate_attr(viddec_workload_t *wl, viddec_mp4_parser_t *parser)
7{
8    uint32_t result = MP4_STATUS_OK;
9    viddec_frame_attributes_t *attr = &(wl->attrs);
10    mp4_VideoObjectLayer_t *vol = &(parser->info.VisualObject.VideoObject);
11
12    memset(attr, 0, sizeof(viddec_frame_attributes_t));
13
14    attr->cont_size.width = vol->video_object_layer_width;
15    attr->cont_size.height = vol->video_object_layer_height;
16
17    // Translate vop_coding_type
18    switch(vol->VideoObjectPlane.vop_coding_type)
19    {
20        case MP4_VOP_TYPE_B:
21            attr->frame_type = VIDDEC_FRAME_TYPE_B;
22            break;
23        case MP4_VOP_TYPE_P:
24            attr->frame_type = VIDDEC_FRAME_TYPE_P;
25            break;
26        case MP4_VOP_TYPE_S:
27            attr->frame_type = VIDDEC_FRAME_TYPE_S;
28            break;
29        case MP4_VOP_TYPE_I:
30            attr->frame_type = VIDDEC_FRAME_TYPE_I;
31            break;
32        default:
33            break;
34    } // switch on vop_coding_type
35
36    attr->mpeg4.top_field_first = vol->VideoObjectPlane.top_field_first;
37
38    return result;
39} // viddec_fw_mp4_populate_attr
40
41uint32_t viddec_fw_mp4_insert_vol_workitem(void *parent, viddec_mp4_parser_t *parser)
42{
43    uint32_t result = MP4_STATUS_OK;
44    viddec_workload_item_t wi;
45    viddec_fw_mp4_vol_info_t vol_info;
46    mp4_VideoObjectLayer_t *vol = &(parser->info.VisualObject.VideoObject);
47
48    memset(&vol_info, 0, sizeof(viddec_fw_mp4_vol_info_t));
49
50    // Get vol_flags
51    viddec_fw_mp4_set_reversible_vlc(&vol_info, vol->reversible_vlc);
52    viddec_fw_mp4_set_data_partitioned(&vol_info, vol->data_partitioned);
53    viddec_fw_mp4_set_resync_marker_disable(&vol_info, vol->resync_marker_disable);
54    viddec_fw_mp4_set_quarter_sample(&vol_info, vol->quarter_sample);
55    viddec_fw_mp4_set_obmc_disable(&vol_info, vol->obmc_disable);
56    viddec_fw_mp4_set_interlaced(&vol_info, vol->interlaced);
57    viddec_fw_mp4_set_vol_shape(&vol_info, vol->video_object_layer_shape);
58    viddec_fw_mp4_set_short_video_header_flag(&vol_info, vol->short_video_header);
59
60    // Get vol_size
61    viddec_fw_mp4_set_vol_width(&vol_info, vol->video_object_layer_width);
62    viddec_fw_mp4_set_vol_height(&vol_info, vol->video_object_layer_height);
63
64    // Get vol_item
65    viddec_fw_mp4_set_quant_type(&vol_info, vol->quant_type);
66    viddec_fw_mp4_set_quant_precision(&vol_info, vol->quant_precision);
67    viddec_fw_mp4_set_sprite_warping_accuracy(&vol_info, vol->sprite_info.sprite_warping_accuracy);
68    viddec_fw_mp4_set_sprite_warping_points(&vol_info, vol->sprite_info.no_of_sprite_warping_points);
69    viddec_fw_mp4_set_sprite_enable(&vol_info, vol->sprite_enable);
70    viddec_fw_mp4_set_vop_time_increment_resolution(&vol_info, vol->vop_time_increment_resolution);
71
72
73    wi.vwi_type = VIDDEC_WORKLOAD_MP4_VOL_INFO;
74    wi.vwi_payload[0] = vol_info.vol_flags;
75    wi.vwi_payload[1] = vol_info.vol_size;
76    wi.vwi_payload[2] = vol_info.vol_item;
77
78    result = viddec_pm_append_workitem(parent, &wi);
79
80    return result;
81} // viddec_fw_mp4_insert_vol_workitem
82
83uint32_t viddec_fw_mp4_insert_vop_workitem(void *parent, viddec_mp4_parser_t *parser)
84{
85    uint32_t result = MP4_STATUS_OK;
86    viddec_workload_item_t wi;
87    viddec_fw_mp4_vop_info_t vop_info;
88    mp4_VideoObjectPlane_t *vop = &(parser->info.VisualObject.VideoObject.VideoObjectPlane);
89    uint32_t byte = 0;
90    unsigned char is_emul;
91
92    memset(&vop_info, 0, sizeof(viddec_fw_mp4_vop_info_t));
93
94    // Get frame_info
95    viddec_fw_mp4_set_past_field_frame(&vop_info, parser->ref_frame[VIDDEC_MP4_INDX_2].is_field);
96    viddec_fw_mp4_set_past_frame_id(&vop_info, VIDDEC_MP4_FRAME_PAST);
97    viddec_fw_mp4_set_future_field_frame(&vop_info, parser->ref_frame[VIDDEC_MP4_INDX_1].is_field);
98    viddec_fw_mp4_set_future_frame_id(&vop_info, VIDDEC_MP4_FRAME_FUTURE);
99    viddec_fw_mp4_set_current_field_frame(&vop_info, parser->ref_frame[VIDDEC_MP4_INDX_0].is_field);
100    viddec_fw_mp4_set_current_frame_id(&vop_info, VIDDEC_MP4_FRAME_CURRENT);
101
102    // HW has a limitation that the enums for PAST(1), FUTURE(2) and CURRENT(0) cannot be changed and
103    // the spec does not support field pictures. Hence the field_frame bits are always zero.
104    // This gives us the constant 0x10200.
105    vop_info.frame_info = 0x10200;
106
107    // Get vop_data
108    // Quant scale is in the video_packet_header or the gob_layer - both of which are parsed by the BSP
109    viddec_fw_mp4_set_vop_quant_scale(&vop_info, 0);
110    viddec_fw_mp4_set_vop_fcode_backward(&vop_info, vop->vop_fcode_backward);
111    viddec_fw_mp4_set_vop_fcode_forward(&vop_info, vop->vop_fcode_forward);
112    viddec_fw_mp4_set_vop_quant(&vop_info, vop->vop_quant);
113    viddec_fw_mp4_set_alternate_vertical_scan_flag(&vop_info, vop->alternate_vertical_scan_flag);
114    viddec_fw_mp4_set_top_field_first(&vop_info, vop->top_field_first);
115    viddec_fw_mp4_set_intra_dc_vlc_thr(&vop_info, vop->intra_dc_vlc_thr);
116    viddec_fw_mp4_set_vop_rounding_type(&vop_info, vop->vop_rounding_type);
117    viddec_fw_mp4_set_vop_coding_type(&vop_info, vop->vop_coding_type);
118
119    // Get vol_item
120    result = viddec_pm_get_au_pos(parent, &vop_info.bit_offset, &byte, &is_emul);
121
122    wi.vwi_type = VIDDEC_WORKLOAD_MP4_VOP_INFO;
123    wi.vwi_payload[0] = vop_info.frame_info;
124    wi.vwi_payload[1] = vop_info.vop_data;
125    wi.vwi_payload[2] = vop_info.bit_offset;
126
127    result = viddec_pm_append_workitem(parent, &wi);
128
129    return result;
130} // viddec_fw_mp4_insert_vop_workitem
131
132uint32_t viddec_fw_mp4_insert_vpsh_workitem(void *parent, viddec_mp4_parser_t *parser)
133{
134    uint32_t result = MP4_STATUS_OK;
135    viddec_workload_item_t wi;
136    viddec_fw_mp4_svh_t svh_info;
137    mp4_VideoObjectPlaneH263 *svh = &(parser->info.VisualObject.VideoObject.VideoObjectPlaneH263);
138
139    memset(&svh_info, 0, sizeof(viddec_fw_mp4_svh_t));
140
141    // Get svh_data
142    viddec_fw_mp4_set_temporal_reference(&svh_info, svh->temporal_reference);
143    viddec_fw_mp4_set_num_macroblocks_in_gob(&svh_info, svh->num_macroblocks_in_gob);
144    viddec_fw_mp4_set_num_gobs_in_vop(&svh_info, svh->num_gobs_in_vop);
145    viddec_fw_mp4_set_num_rows_in_gob(&svh_info, svh->num_rows_in_gob);
146
147    wi.vwi_type = VIDDEC_WORKLOAD_MP4_SVH;
148    wi.vwi_payload[0] = svh_info.svh_data;
149    wi.vwi_payload[1] = svh_info.pad1;
150    wi.vwi_payload[2] = svh_info.pad2;
151
152    result = viddec_pm_append_workitem(parent, &wi);
153
154    return result;
155} // viddec_fw_mp4_insert_vpsh_workitem
156
157uint32_t viddec_fw_mp4_insert_sprite_workitem(void *parent, viddec_mp4_parser_t *parser)
158{
159    uint32_t result = MP4_STATUS_OK;
160    viddec_workload_item_t wi;
161    viddec_fw_mp4_sprite_trajectory_t sprite_info;
162    mp4_VideoObjectLayer_t *vol = &(parser->info.VisualObject.VideoObject);
163    mp4_VideoObjectPlane_t *vop = &(parser->info.VisualObject.VideoObject.VideoObjectPlane);
164    uint8_t no_of_entries_per_item = 3;
165    uint8_t no_of_sprite_workitems = 0;
166    uint8_t warp_index = 0;
167    int i, j;
168
169    if(!vol->sprite_info.no_of_sprite_warping_points)
170        return result;
171
172    no_of_sprite_workitems = (vol->sprite_info.no_of_sprite_warping_points > 3) ? 2 : 1;
173
174    for(i=0; i<no_of_sprite_workitems; i++)
175    {
176        memset(&sprite_info, 0, sizeof(viddec_fw_mp4_sprite_trajectory_t));
177
178        for(j=0; j<no_of_entries_per_item; j++)
179        {
180            if(warp_index < vol->sprite_info.no_of_sprite_warping_points)
181            {
182                viddec_fw_mp4_set_warping_point_index(sprite_info.warping_mv_code[j], warp_index);
183                viddec_fw_mp4_set_warping_mv_code_du(sprite_info.warping_mv_code[j], vop->warping_mv_code_du[warp_index]);
184                viddec_fw_mp4_set_warping_mv_code_dv(sprite_info.warping_mv_code[j], vop->warping_mv_code_dv[warp_index]);
185            }
186            else
187            {
188               sprite_info.warping_mv_code[j] = 0xF << 28;
189            }
190            warp_index++;
191        }
192
193        wi.vwi_type = VIDDEC_WORKLOAD_MP4_SPRT_TRAJ;
194        wi.vwi_payload[0] = sprite_info.warping_mv_code[0];
195        wi.vwi_payload[1] = sprite_info.warping_mv_code[1];
196        wi.vwi_payload[2] = sprite_info.warping_mv_code[2];
197
198        result = viddec_pm_append_workitem(parent, &wi);
199    }
200
201    return result;
202} // viddec_fw_mp4_insert_sprite_workitem
203
204uint32_t viddec_fw_mp4_insert_bvop_workitem(void *parent, viddec_mp4_parser_t *parser)
205{
206    uint32_t result = MP4_STATUS_OK;
207    viddec_workload_item_t wi;
208    mp4_VideoObjectLayer_t *vol = &(parser->info.VisualObject.VideoObject);
209
210    wi.vwi_type = VIDDEC_WORKLOAD_MP4_BVOP_INFO;
211    wi.vwi_payload[0] = vol->Tframe;
212    wi.vwi_payload[1] = vol->TRD;
213    wi.vwi_payload[2] = vol->TRB;
214
215    result = viddec_pm_append_workitem(parent, &wi);
216
217    return result;
218} // viddec_fw_mp4_insert_bvop_workitem
219
220uint32_t viddec_fw_mp4_insert_qmat(void *parent, uint8_t intra_quant_flag, uint32_t *qmat)
221{
222    uint32_t result = MP4_STATUS_OK;
223    viddec_workload_item_t wi;
224    uint8_t i;
225
226    // No of items = (64/4 Dwords / 3 entries per workload item)
227    // 64 8b entries => 64 * 8 / 32 DWORDS => 64/4 DWORDS => 16 DWORDS
228    // Each item can store 3 DWORDS, 16 DWORDS => 16/3 items => 6 items
229    for(i=0; i<6; i++)
230    {
231        memset(&wi, 0, sizeof(viddec_workload_item_t));
232
233        if(intra_quant_flag)
234            wi.vwi_type = VIDDEC_WORKLOAD_MP4_IQUANT;
235        else
236            wi.vwi_type = VIDDEC_WORKLOAD_MP4_NIQUANT;
237
238        if(i == 6)
239        {
240            wi.vwi_payload[0] = qmat[0];
241            wi.vwi_payload[1] = 0;
242            wi.vwi_payload[2] = 0;
243        }
244        else
245        {
246            wi.vwi_payload[0] = qmat[0];
247            wi.vwi_payload[1] = qmat[1];
248            wi.vwi_payload[2] = qmat[2];
249        }
250
251        qmat += 3;
252
253        result = viddec_pm_append_workitem(parent, &wi);
254    }
255
256    return result;
257} // viddec_fw_mp4_insert_qmat
258
259uint32_t viddec_fw_mp4_insert_inversequant_workitem(void *parent, mp4_VOLQuant_mat_t *qmat)
260{
261    uint32_t result = MP4_STATUS_OK;
262
263    if(qmat->load_intra_quant_mat)
264    {
265        result = viddec_fw_mp4_insert_qmat(parent, true, (uint32_t *) &(qmat->intra_quant_mat));
266    }
267
268    if(qmat->load_nonintra_quant_mat)
269    {
270        result = viddec_fw_mp4_insert_qmat(parent, false, (uint32_t *) &(qmat->nonintra_quant_mat));
271    }
272
273    return result;
274} // viddec_fw_mp4_insert_inversequant_workitem
275
276uint32_t viddec_fw_mp4_insert_past_frame_workitem(void *parent)
277{
278    uint32_t result = MP4_STATUS_OK;
279    viddec_workload_item_t wi;
280
281    wi.vwi_type = VIDDEC_WORKLOAD_MP4_PAST_FRAME;
282    wi.ref_frame.reference_id = 0;
283    wi.ref_frame.luma_phys_addr = 0;
284    wi.ref_frame.chroma_phys_addr = 0;
285    result = viddec_pm_append_workitem(parent, &wi);
286
287    return result;
288} // viddec_fw_mp4_insert_past_frame_workitem
289
290uint32_t viddec_fw_mp4_insert_future_frame_workitem(void *parent)
291{
292    uint32_t result = MP4_STATUS_OK;
293    viddec_workload_item_t wi;
294
295    wi.vwi_type = VIDDEC_WORKLOAD_MP4_FUTURE_FRAME;
296    wi.ref_frame.reference_id = 0;
297    wi.ref_frame.luma_phys_addr = 0;
298    wi.ref_frame.chroma_phys_addr = 0;
299    result = viddec_pm_append_workitem(parent, &wi);
300
301    return result;
302} // viddec_fw_mp4_insert_future_frame_workitem
303
304uint32_t viddec_fw_mp4_insert_reorder_workitem(void *parent)
305{
306    uint32_t result = MP4_STATUS_OK;
307    viddec_workload_item_t wi;
308
309    // Move frame at location 1 of the reference table to location 0
310    wi.vwi_type = VIDDEC_WORKLOAD_REFERENCE_FRAME_REORDER;
311    wi.ref_reorder.ref_table_offset = 0;
312    wi.ref_reorder.ref_reorder_00010203 = 0x01010203;
313    wi.ref_reorder.ref_reorder_04050607 = 0x04050607;
314
315    result = viddec_pm_append_workitem(parent, &wi);
316
317    return result;
318} // viddec_fw_mp4_insert_reorder_workitem
319
320uint32_t viddec_fw_mp4_emit_workload(void *parent, void *ctxt)
321{
322    uint32_t result = 0;
323    viddec_mp4_parser_t *parser = (viddec_mp4_parser_t *) ctxt;
324    viddec_workload_t *wl = viddec_pm_get_header(parent);
325
326    result = viddec_fw_mp4_populate_attr(wl, parser);
327    result = viddec_fw_mp4_insert_vol_workitem(parent, parser);
328    result = viddec_fw_mp4_insert_vop_workitem(parent, parser);
329    result = viddec_fw_mp4_insert_sprite_workitem(parent, parser);
330    result = viddec_fw_mp4_insert_inversequant_workitem(parent, &(parser->info.VisualObject.VideoObject.quant_mat_info));
331
332    if(parser->info.VisualObject.VideoObject.short_video_header)
333      result = viddec_fw_mp4_insert_vpsh_workitem(parent, parser);
334
335    if(!parser->info.VisualObject.VideoObject.VideoObjectPlane.vop_coded)
336        wl->is_reference_frame |= WORKLOAD_SKIPPED_FRAME;
337
338    // Send reference re-order tag for all reference frame types
339    if (parser->info.VisualObject.VideoObject.VideoObjectPlane.vop_coding_type != MP4_VOP_TYPE_B)
340    {
341        result = viddec_fw_mp4_insert_reorder_workitem(parent);
342    }
343
344    // Handle vop_coding_type based information
345    switch(parser->info.VisualObject.VideoObject.VideoObjectPlane.vop_coding_type)
346    {
347        case MP4_VOP_TYPE_B:
348            result = viddec_fw_mp4_insert_bvop_workitem(parent, parser);
349            result = viddec_fw_mp4_insert_past_frame_workitem(parent);
350            result = viddec_fw_mp4_insert_future_frame_workitem(parent);
351            break;
352        case MP4_VOP_TYPE_P:
353        case MP4_VOP_TYPE_S:
354            result = viddec_fw_mp4_insert_past_frame_workitem(parent);
355            // Deliberate fall-thru to type I
356        case MP4_VOP_TYPE_I:
357            wl->is_reference_frame |= WORKLOAD_REFERENCE_FRAME | (1 & WORKLOAD_REFERENCE_FRAME_BMASK);
358            // Swap reference information
359            parser->ref_frame[VIDDEC_MP4_INDX_2] = parser->ref_frame[VIDDEC_MP4_INDX_1];
360            parser->ref_frame[VIDDEC_MP4_INDX_1] = parser->ref_frame[VIDDEC_MP4_INDX_0];
361            break;
362            break;
363        default:
364            break;
365    } // switch on vop_coding_type
366
367    result = viddec_pm_append_pixeldata(parent);
368
369    return result;
370} // viddec_fw_mp4_emit_workload
371
372