1#include "viddec_mp4_visualobject.h"
2
3static inline uint8_t mp4_pvt_isValid_verID(uint8_t id)
4{
5    uint8_t ret=true;
6    switch(id)
7    {
8        case 1:
9        case 2:
10        case 4:
11        case 5:
12        {
13            break;
14        }
15        default:
16        {
17            ret = false;
18            break;
19        }
20    }
21    return ret;
22} // mp4_pvt_isValid_verID
23
24static mp4_Status_t mp4_Parse_video_signal_type(void *parent, mp4_VideoSignalType_t *vidSignal)
25{
26    uint32_t data=0;
27    int32_t getbits=0;
28    mp4_Status_t ret = MP4_STATUS_PARSE_ERROR;
29
30    /* Set default values defined in spec first */
31    vidSignal->video_format = 5;
32    vidSignal->video_range = 0;
33    vidSignal->colour_primaries = 1;
34    vidSignal->transfer_characteristics = 1;
35    vidSignal->matrix_coefficients = 1;
36    do
37    {
38        getbits = viddec_pm_get_bits(parent, &data, 1);
39        BREAK_GETBITS_FAIL(getbits, ret);
40        vidSignal->is_video_signal_type = (data > 0);
41        if(vidSignal->is_video_signal_type)
42        {
43            getbits = viddec_pm_get_bits(parent, &data, 5);
44            BREAK_GETBITS_FAIL(getbits, ret);
45            vidSignal->is_colour_description = data & 0x1;
46            vidSignal->video_range = ((data & 0x2) > 0);
47            data =  data >> 2;
48            vidSignal->video_format = data & 0x7;
49            if(vidSignal->is_colour_description)
50            {
51                getbits = viddec_pm_get_bits(parent, &data, 24);
52                BREAK_GETBITS_FAIL(getbits, ret);
53                vidSignal->colour_primaries = (data >> 16) & 0xFF;
54                vidSignal->transfer_characteristics = (data >> 8) & 0xFF;
55                vidSignal->matrix_coefficients = data & 0xFF;
56            }
57        }
58        ret = MP4_STATUS_OK;
59    }while(0);
60
61    return ret;
62} // mp4_Parse_video_signal_type
63
64void mp4_set_hdr_bitstream_error(viddec_mp4_parser_t *parser, uint8_t hdr_flag, mp4_Status_t parse_status)
65{
66    //DEB("Entering mp4_set_hdr_bitstream_error: bs_err: 0x%x, hdr: %d, parse_status: %d\n",
67    //  parser->bitstream_error, hdr_flag, parse_status);
68
69    if(hdr_flag)
70    {
71        if(parse_status & MP4_STATUS_NOTSUPPORT)
72            parser->bitstream_error |= MP4_BS_ERROR_HDR_UNSUP;
73        if(parse_status & MP4_STATUS_PARSE_ERROR)
74            parser->bitstream_error |= MP4_BS_ERROR_HDR_PARSE;
75        if(parse_status & MP4_STATUS_REQD_DATA_ERROR)
76            parser->bitstream_error |= MP4_BS_ERROR_HDR_NONDEC;
77        parser->bitstream_error &= MP4_HDR_ERROR_MASK;
78    }
79    else
80    {
81        if(parse_status & MP4_STATUS_NOTSUPPORT)
82            parser->bitstream_error |= MP4_BS_ERROR_FRM_UNSUP;
83        if(parse_status & MP4_STATUS_PARSE_ERROR)
84            parser->bitstream_error |= MP4_BS_ERROR_FRM_PARSE;
85        if(parse_status & MP4_STATUS_REQD_DATA_ERROR)
86            parser->bitstream_error |= MP4_BS_ERROR_FRM_NONDEC;
87    }
88
89    //DEB("Exiting mp4_set_hdr_bitstream_error: bs_err: 0x%x\n", parser->bitstream_error);
90
91    return;
92} // mp4_set_hdr_bitstream_error
93
94mp4_Status_t mp4_Parse_VisualSequence(void *parent, viddec_mp4_parser_t *parser)
95{
96    uint32_t data=0;
97    int32_t getbits=0;
98    mp4_Status_t ret = MP4_STATUS_PARSE_ERROR;
99
100    getbits = viddec_pm_get_bits(parent, &data, 8);
101    if(getbits != -1)
102    {
103        parser->info.profile_and_level_indication = data & 0xFF;
104        // If present, check for validity
105        switch(parser->info.profile_and_level_indication)
106        {
107            case MP4_SIMPLE_PROFILE_LEVEL_0:
108            case MP4_SIMPLE_PROFILE_LEVEL_1:
109            case MP4_SIMPLE_PROFILE_LEVEL_2:
110            case MP4_SIMPLE_PROFILE_LEVEL_3:
111            case MP4_SIMPLE_PROFILE_LEVEL_4a:
112            case MP4_SIMPLE_PROFILE_LEVEL_5:
113            case MP4_SIMPLE_PROFILE_LEVEL_6:
114            case MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_0:
115            case MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_1:
116            case MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_2:
117            case MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_3:
118            case MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_4:
119            case MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_5:
120            case MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_3B:
121                parser->bitstream_error = MP4_BS_ERROR_NONE;
122                ret = MP4_STATUS_OK;
123                break;
124            default:
125                parser->bitstream_error = MP4_BS_ERROR_HDR_UNSUP | MP4_BS_ERROR_HDR_NONDEC;
126                break;
127        }
128    }
129    else
130    {
131        parser->bitstream_error = MP4_BS_ERROR_HDR_PARSE | MP4_BS_ERROR_HDR_NONDEC;
132    }
133
134    return ret;
135} // mp4_Parse_VisualSequence
136
137mp4_Status_t mp4_Parse_VisualObject(void *parent, viddec_mp4_parser_t *parser)
138{
139    mp4_Info_t *pInfo = &(parser->info);
140    mp4_VisualObject_t *visObj = &(pInfo->VisualObject);
141    uint32_t data=0;
142    int32_t getbits=0;
143    mp4_Status_t ret = MP4_STATUS_PARSE_ERROR;
144
145    do
146    {
147        getbits = viddec_pm_get_bits(parent, &data, 1);
148        BREAK_GETBITS_FAIL(getbits, ret);
149        visObj->is_visual_object_identifier = (data > 0);
150
151        visObj->visual_object_verid = 1; /* Default value as per spec */
152        if (visObj->is_visual_object_identifier)
153        {
154            viddec_pm_get_bits(parent, &data, 7);
155            visObj->visual_object_priority = data & 0x7;
156            data = data >> 3;
157            if(mp4_pvt_isValid_verID(data & 0xF))
158            {
159                visObj->visual_object_verid = data & 0xF;
160            }
161            else
162            {
163                DEB("Warning: Unsupported visual_object_verid\n");
164                parser->bitstream_error |= MP4_BS_ERROR_HDR_UNSUP;
165                // Continue parsing as it is not a required field for decoder
166            }
167        }
168
169        getbits = viddec_pm_get_bits(parent, &data, 4);
170        BREAK_GETBITS_FAIL(getbits, ret);
171        visObj->visual_object_type = data;
172        if (visObj->visual_object_type != MP4_VISUAL_OBJECT_TYPE_VIDEO)
173        {
174            /* VIDEO is the only supported type */
175            DEB("Error: Unsupported object: visual_object_type != video ID\n");
176            parser->bitstream_error |= MP4_BS_ERROR_HDR_UNSUP;
177            break;
178        }
179
180        /* Not required to check for visual_object_type as we already handle it above */
181        ret = mp4_Parse_video_signal_type(parent, &(visObj->VideoSignalType));
182
183        // No need to check for user data or visual object layer because they have a different start code
184        // and will not be part of this header
185
186    } while(0);
187
188    mp4_set_hdr_bitstream_error(parser, true, ret);
189
190    // POPULATE WORKLOAD ITEM
191    {
192        viddec_workload_item_t wi;
193        mp4_VideoSignalType_t *vst = &(visObj->VideoSignalType);
194
195        wi.vwi_type = VIDDEC_WORKLOAD_MPEG4_VISUAL_SEQ_OBJ;
196
197        wi.mp4_vs_vo.vs_item = 0;
198        wi.mp4_vs_vo.video_signal_type = 0;
199        wi.mp4_vs_vo.color_desc = 0;
200
201        viddec_fw_mp4_vs_set_profile_and_level_indication(&wi.mp4_vs_vo, pInfo->profile_and_level_indication);
202
203        viddec_fw_mp4_vo_set_video_signal_type(&wi.mp4_vs_vo, vst->is_video_signal_type);
204        if(vst->is_video_signal_type)
205        {
206            viddec_fw_mp4_vo_set_video_range(&wi.mp4_vs_vo, vst->video_range);
207            viddec_fw_mp4_vo_set_video_format(&wi.mp4_vs_vo, vst->video_format);
208            viddec_fw_mp4_vo_set_colour_description(&wi.mp4_vs_vo, vst->is_colour_description);
209            if(vst->is_colour_description)
210            {
211                viddec_fw_mp4_vo_set_transfer_char(&wi.mp4_vs_vo, vst->transfer_characteristics);
212                viddec_fw_mp4_vo_set_color_primaries(&wi.mp4_vs_vo, vst->colour_primaries);
213            }
214        }
215
216        ret = viddec_pm_append_workitem(parent, &wi);
217        if(ret == 1)
218            ret = MP4_STATUS_OK;
219    }
220
221    return ret;
222} // mp4_Parse_VisualObject
223
224mp4_Status_t mp4_Parse_UserData(void *parent, viddec_mp4_parser_t *parser)
225{
226    mp4_Status_t ret = MP4_STATUS_PARSE_ERROR;
227    uint32_t user_data;
228    viddec_workload_item_t wi;
229
230    DEB("ParseUser-prev_sc: 0x%x\n", parser->prev_sc);
231
232    /* find the scope based on start code sc */
233    switch(parser->prev_sc) {
234        case MP4_SC_VISUAL_OBJECT_SEQUENCE:
235            wi.vwi_type = VIDDEC_WORKLOAD_SEQ_USER_DATA;
236            break;
237        case MP4_SC_VISUAL_OBJECT:
238            wi.vwi_type = VIDDEC_WORKLOAD_VISUAL_OBJ_USER_DATA;
239            break;
240        case MP4_SC_GROUP_OF_VOP:
241            wi.vwi_type = VIDDEC_WORKLOAD_GOP_USER_DATA;
242            break;
243        case MP4_SC_VIDEO_OBJECT_LAYER_MIN:
244            wi.vwi_type = VIDDEC_WORKLOAD_VIDEO_OBJ_USER_DATA;
245            break;
246        default:
247            wi.vwi_type = VIDDEC_WORKLOAD_INVALID; //ERROR - should not happen
248            break;
249    }
250
251    /* Read 1 byte of user data and store it in workitem for the current stream level (VS/VO/VOL/GVOP).
252       Keep adding data payloads till it reaches size 11. When it is 11, the maximum user data payload size,
253       append the workitem. This loop is repeated till all user data is extracted and appended. */
254    wi.user_data.size = 0;
255    while(viddec_pm_get_bits(parent, &user_data, 8) != -1)
256    {
257        /* Store the valid byte in data payload */
258        wi.user_data.data_payload[wi.user_data.size] = user_data;
259        wi.user_data.size++;
260
261        /* When size exceeds payload size, append workitem and continue */
262        if (wi.user_data.size >= 11)
263        {
264            viddec_pm_setup_userdata(&wi);
265            ret = viddec_pm_append_workitem(parent, &wi);
266            wi.user_data.size = 0;
267        }
268    }
269    /* If size is not 0, append remaining user data. */
270    if (wi.user_data.size > 0)
271    {
272        int i;
273        for(i=wi.user_data.size;i<11;i++)
274        {
275            wi.user_data.data_payload[i] = 0;
276        }
277        viddec_pm_setup_userdata(&wi);
278        ret = viddec_pm_append_workitem(parent, &wi);
279        wi.user_data.size = 0;
280    }
281
282    if(ret == 1)
283        ret = MP4_STATUS_OK;
284
285    return ret;
286} // mp4_Parse_UserData
287
288