| /* INTEL CONFIDENTIAL |
| * Copyright (c) 2009, 2012 Intel Corporation. All rights reserved. |
| * |
| * The source code contained or described herein and all documents |
| * related to the source code ("Material") are owned by Intel |
| * Corporation or its suppliers or licensors. Title to the |
| * Material remains with Intel Corporation or its suppliers and |
| * licensors. The Material contains trade secrets and proprietary |
| * and confidential information of Intel or its suppliers and |
| * licensors. The Material is protected by worldwide copyright and |
| * trade secret laws and treaty provisions. No part of the Material |
| * may be used, copied, reproduced, modified, published, uploaded, |
| * posted, transmitted, distributed, or disclosed in any way without |
| * Intel's prior express written permission. |
| * |
| * No license under any patent, copyright, trade secret or other |
| * intellectual property right is granted to or conferred upon you |
| * by disclosure or delivery of the Materials, either expressly, by |
| * implication, inducement, estoppel or otherwise. Any license |
| * under such intellectual property rights must be express and |
| * approved by Intel in writing. |
| * |
| */ |
| |
| |
| |
| #include <dlfcn.h> |
| |
| #include <string.h> |
| #include "vbp_loader.h" |
| #include "vbp_utils.h" |
| #include "vbp_mp42_parser.h" |
| #include "vbp_common.h" |
| #include "viddec_mp4_parse.h" |
| |
| |
| |
| typedef struct vbp_mp42_parser_private_t vbp_mp42_parser_private; |
| |
| struct vbp_mp42_parser_private_t |
| { |
| bool short_video_header; |
| }; |
| |
| static uint8 mp4_aspect_ratio_table[][2] = |
| { |
| // forbidden |
| {0, 0}, |
| {1, 1}, |
| {12, 11}, |
| {10, 11}, |
| {16, 11}, |
| {40, 33}, |
| |
| // reserved |
| {0, 0} |
| }; |
| |
| |
| /* |
| * Some divX avi files contains 2 frames in one gstbuffer. |
| */ |
| |
| |
| uint32 vbp_get_sc_pos_mp42( |
| uint8 *buf, |
| uint32 length, |
| uint32 *sc_end_pos, |
| uint8 *is_normal_sc, |
| uint8* resync_marker, |
| const bool svh_search); |
| |
| void vbp_on_vop_mp42(vbp_context *pcontext, int list_index); |
| void vbp_on_vop_svh_mp42(vbp_context *pcontext, int list_index); |
| void vbp_fill_codec_data(vbp_context *pcontext); |
| vbp_picture_data_mp42* vbp_get_mp42_picture_data(vbp_data_mp42 * query_data); |
| uint32 vbp_process_slices_mp42(vbp_context *pcontext, int list_index); |
| uint32 vbp_process_slices_svh_mp42(vbp_context *pcontext, int list_index); |
| uint32 vbp_process_video_packet_mp42(vbp_context *pcontext); |
| |
| static inline uint32 vbp_sprite_trajectory_mp42( |
| void *parent, |
| mp4_VideoObjectLayer_t *vidObjLay, |
| mp4_VideoObjectPlane_t *vidObjPlane); |
| |
| |
| static inline uint32 vbp_sprite_dmv_length_mp42( |
| void * parent, |
| int32_t *dmv_length); |
| |
| |
| /** |
| * |
| */ |
| uint32 vbp_init_parser_entries_mp42( vbp_context *pcontext) |
| { |
| if (NULL == pcontext->parser_ops) |
| { |
| // absolutely impossible, just sanity check |
| return VBP_PARM; |
| } |
| pcontext->parser_ops->init = dlsym(pcontext->fd_parser, "viddec_mp4_init"); |
| if (pcontext->parser_ops->init == NULL) |
| { |
| ETRACE ("Failed to set entry point." ); |
| return VBP_LOAD; |
| } |
| |
| pcontext->parser_ops->parse_sc = NULL; |
| pcontext->parser_ops->parse_syntax = dlsym(pcontext->fd_parser, "viddec_mp4_parse"); |
| if (pcontext->parser_ops->parse_syntax == NULL) |
| { |
| ETRACE ("Failed to set entry point." ); |
| return VBP_LOAD; |
| } |
| |
| pcontext->parser_ops->get_cxt_size =dlsym(pcontext->fd_parser, "viddec_mp4_get_context_size"); |
| if (pcontext->parser_ops->get_cxt_size == NULL) |
| { |
| ETRACE ("Failed to set entry point." ); |
| return VBP_LOAD; |
| } |
| |
| /* entry point not needed */ |
| pcontext->parser_ops->flush = NULL; |
| |
| return VBP_OK; |
| } |
| |
| |
| /* |
| * For the codec_data passed by gstreamer |
| */ |
| uint32 vbp_parse_init_data_mp42(vbp_context *pcontext) |
| { |
| uint32 ret = VBP_OK; |
| ret = vbp_parse_start_code_mp42(pcontext); |
| return ret; |
| } |
| |
| uint32 vbp_process_parsing_result_mp42(vbp_context *pcontext, int list_index) |
| { |
| vbp_data_mp42 *query_data = (vbp_data_mp42 *) pcontext->query_data; |
| viddec_mp4_parser_t *parser = |
| (viddec_mp4_parser_t *) &(pcontext->parser_cxt->codec_data[0]); |
| vbp_mp42_parser_private *parser_private = (vbp_mp42_parser_private *)pcontext->parser_private; |
| |
| uint8 is_svh = 0; |
| uint32 current_sc = parser->current_sc; |
| is_svh = parser->cur_sc_prefix ? false : true; |
| |
| if (!is_svh) |
| { |
| // remove prefix from current_sc |
| current_sc &= 0x0FF; |
| switch (current_sc) |
| { |
| case MP4_SC_VISUAL_OBJECT_SEQUENCE: |
| VTRACE ("Visual Object Sequence is parsed.\n"); |
| query_data->codec_data.profile_and_level_indication |
| = parser->info.profile_and_level_indication; |
| VTRACE ("profile_and_level_indication = 0x%x\n", parser->info.profile_and_level_indication); |
| break; |
| |
| case MP4_SC_VIDEO_OBJECT_PLANE: |
| //VTRACE ("Video Object Plane is parsed.\n"); |
| vbp_on_vop_mp42(pcontext, list_index); |
| break; |
| |
| default: |
| if ((current_sc >= MP4_SC_VIDEO_OBJECT_LAYER_MIN) && |
| (current_sc <= MP4_SC_VIDEO_OBJECT_LAYER_MAX)) |
| { |
| VTRACE ("Video Object Layer is parsed\n"); |
| parser_private->short_video_header = FALSE; |
| vbp_fill_codec_data(pcontext); |
| } |
| else if (current_sc <= MP4_SC_VIDEO_OBJECT_MAX && |
| current_sc >= MP4_SC_VIDEO_OBJECT_MIN) |
| { |
| if (parser->sc_seen == MP4_SC_SEEN_SVH) |
| { |
| // this should never happen!!!! |
| WTRACE ("Short video header is parsed.\n"); |
| // vbp_on_vop_svh_mp42(pcontext, list_index); |
| return VBP_TYPE; |
| } |
| } |
| break; |
| } |
| } |
| else |
| { |
| if (parser->sc_seen == MP4_SC_SEEN_SVH) |
| { |
| //VTRACE ("Short video header is parsed.\n"); |
| vbp_on_vop_svh_mp42(pcontext, list_index); |
| } |
| } |
| |
| return VBP_OK; |
| } |
| |
| |
| |
| /* |
| * partial frame handling: |
| * |
| * h.263: picture header is lost if the first GOB is discarded, a redudant pic header must be |
| * conveyed in the packet (RFC 4629) for each following GOB, otherwise, |
| * picture can't be decoded. |
| * |
| * MPEG4: VideoObjectPlane header is lost if the first slice is discarded. However, picture |
| * is still decodable as long as the header_extension_code is 1 in video_packet_header. |
| * |
| *MPEG-4 with short header: video_plane_with_short_header is lost if the first GOB |
| * is discarded. As this header is not duplicated (RFC 3016), picture is not decodable. |
| * |
| * In sum: |
| * If buffer contains the 32-bit start code (0x000001xx), proceed as normal. |
| * |
| * If buffer contains 22-bits of "0000 0000 0000 0000 1000 00", which indicates h.263 |
| * picture start code or short_video_start_marker, proceed as normal. |
| * |
| * If buffer contains 22-bits of "0000 0000 0000 0000 1XXX XX", (when XXX XX starts from 000 01), which |
| * indicates h.263 Group Start code or gob_resync_marker of gob_layer in MPEG-4 with |
| * short header, we should report packet as a partial frame - no more parsing is needed. |
| * |
| * If buffer contains a string of 0 between 16 bits and 22 bits, followed by 1-bit of '1', which indicates a resync-marker, |
| * the buffer will be immeidately parsed and num_items is set to 0. |
| */ |
| uint32 vbp_parse_start_code_mp42(vbp_context *pcontext) |
| { |
| viddec_pm_cxt_t *cxt = pcontext->parser_cxt; |
| uint8 *buf = NULL; |
| uint32 size = 0; |
| uint32 sc_end_pos = -1; |
| uint32 bytes_parsed = 0; |
| viddec_mp4_parser_t *pinfo = NULL; |
| vbp_data_mp42 *query_data = (vbp_data_mp42 *) pcontext->query_data; |
| vbp_mp42_parser_private *parser_private = (vbp_mp42_parser_private *)pcontext->parser_private; |
| |
| |
| // reset query data for the new sample buffer |
| query_data->number_picture_data= 0; |
| query_data->number_pictures = 0; |
| |
| // emulation prevention byte is not needed |
| cxt->getbits.is_emul_reqd = 0; |
| |
| cxt->list.num_items = 0; |
| cxt->list.data[0].stpos = 0; |
| cxt->list.data[0].edpos = cxt->parse_cubby.size; |
| |
| buf = cxt->parse_cubby.buf; |
| size = cxt->parse_cubby.size; |
| |
| pinfo = (viddec_mp4_parser_t *) &(cxt->codec_data[0]); |
| |
| uint8 is_normal_sc = 0; |
| uint8 resync_marker = 0; |
| uint32 found_sc = 0; |
| uint32 ret = VBP_OK; |
| |
| while (1) |
| { |
| found_sc = vbp_get_sc_pos_mp42( |
| buf + bytes_parsed, |
| size - bytes_parsed, |
| &sc_end_pos, |
| &is_normal_sc, |
| &resync_marker, |
| parser_private->short_video_header); |
| |
| if (found_sc) |
| { |
| cxt->list.data[cxt->list.num_items].stpos = bytes_parsed + sc_end_pos - 3; |
| if (cxt->list.num_items != 0) |
| { |
| cxt->list.data[cxt->list.num_items - 1].edpos = bytes_parsed + sc_end_pos - 3; |
| } |
| bytes_parsed += sc_end_pos; |
| |
| cxt->list.num_items++; |
| pinfo->cur_sc_prefix = is_normal_sc; |
| } |
| else |
| { |
| if (cxt->list.num_items != 0) |
| { |
| cxt->list.data[cxt->list.num_items - 1].edpos = cxt->parse_cubby.size; |
| break; |
| } |
| else |
| { |
| WTRACE ("No start-code is found in cubby buffer! The size of cubby is %d\n", size); |
| cxt->list.num_items = 1; |
| cxt->list.data[0].stpos = 0; |
| cxt->list.data[0].edpos = cxt->parse_cubby.size; |
| |
| if (resync_marker) |
| { |
| // either the first slice (GOB) is lost or parser receives a single slice (GOB) |
| if (parser_private->short_video_header) |
| { |
| // TODO: revisit if HW supportd GOB layer decoding for h.263 |
| WTRACE("Partial frame: GOB buffer.\n"); |
| ret = VBP_PARTIAL; |
| } |
| else |
| { |
| WTRACE("Partial frame: video packet header buffer.\n"); |
| ret = vbp_process_video_packet_mp42(pcontext); |
| } |
| |
| // set num_items to 0 so buffer will not be parsed again |
| cxt->list.num_items = 0; |
| } |
| else |
| { |
| ETRACE("Invalid data received.\n"); |
| cxt->list.num_items = 0; |
| return VBP_DATA; |
| } |
| |
| break; |
| } |
| } |
| } |
| |
| return ret; |
| } |
| |
| uint32 vbp_populate_query_data_mp42(vbp_context *pcontext) |
| { |
| #if 0 |
| vbp_dump_query_data(pcontext); |
| #endif |
| return VBP_OK; |
| } |
| |
| vbp_picture_data_mp42* vbp_get_mp42_picture_data(vbp_data_mp42 * query_data) |
| { |
| vbp_picture_data_mp42 *picture_data = query_data->picture_data; |
| int num_pictures = query_data->number_picture_data; |
| while (num_pictures > 1) |
| { |
| picture_data = picture_data->next_picture_data; |
| num_pictures--; |
| } |
| |
| return picture_data; |
| } |
| |
| void vbp_fill_codec_data(vbp_context *pcontext) |
| { |
| viddec_mp4_parser_t *parser = |
| (viddec_mp4_parser_t *) &(pcontext->parser_cxt->codec_data[0]); |
| vbp_data_mp42 *query_data = (vbp_data_mp42 *) pcontext->query_data; |
| vbp_codec_data_mp42* codec_data = &(query_data->codec_data); |
| vbp_mp42_parser_private *parser_private = (vbp_mp42_parser_private *)pcontext->parser_private; |
| |
| codec_data->bit_rate = parser->info.VisualObject.VideoObject.VOLControlParameters.bit_rate; |
| |
| codec_data->profile_and_level_indication |
| = parser->info.profile_and_level_indication; |
| |
| codec_data->video_object_layer_width = |
| parser->info.VisualObject.VideoObject.video_object_layer_width; |
| |
| codec_data->video_object_layer_height = |
| parser->info.VisualObject.VideoObject.video_object_layer_height; |
| |
| if (parser->info.VisualObject.VideoSignalType.is_video_signal_type) |
| { |
| codec_data->video_format = |
| parser->info.VisualObject.VideoSignalType.video_format; |
| } |
| else |
| { |
| // Unspecified video format |
| codec_data->video_format = 5; |
| } |
| |
| codec_data->video_range = |
| parser->info.VisualObject.VideoSignalType.video_range; |
| |
| if (parser->info.VisualObject.VideoSignalType.is_colour_description) |
| { |
| codec_data->matrix_coefficients = |
| parser->info.VisualObject.VideoSignalType.matrix_coefficients; |
| } |
| else if (parser_private->short_video_header) |
| { |
| // SMPTE 170M |
| codec_data->matrix_coefficients = 6; |
| } |
| else |
| { |
| // ITU-R Recommendation BT.709 |
| codec_data->matrix_coefficients = 1; |
| } |
| |
| codec_data->short_video_header = parser_private->short_video_header; |
| |
| // aspect ratio |
| codec_data->aspect_ratio_info = parser->info.VisualObject.VideoObject.aspect_ratio_info; |
| if (codec_data->aspect_ratio_info < 6) |
| { |
| codec_data->par_width = mp4_aspect_ratio_table[codec_data->aspect_ratio_info][0]; |
| codec_data->par_height = mp4_aspect_ratio_table[codec_data->aspect_ratio_info][1]; |
| } |
| else if (codec_data->aspect_ratio_info == 15) |
| { |
| codec_data->par_width = parser->info.VisualObject.VideoObject.aspect_ratio_info_par_width; |
| codec_data->par_height = parser->info.VisualObject.VideoObject.aspect_ratio_info_par_height; |
| } |
| else |
| { |
| codec_data->par_width = 0; |
| codec_data->par_height = 0; |
| } |
| } |
| |
| void vbp_fill_slice_data(vbp_context *pcontext, int list_index) |
| { |
| viddec_mp4_parser_t *parser = |
| (viddec_mp4_parser_t *) &(pcontext->parser_cxt->codec_data[0]); |
| |
| if (!parser->info.VisualObject.VideoObject.short_video_header) |
| { |
| vbp_process_slices_mp42(pcontext, list_index); |
| } |
| else |
| { |
| vbp_process_slices_svh_mp42(pcontext, list_index); |
| } |
| } |
| |
| void vbp_fill_picture_param(vbp_context *pcontext, uint8 new_picture_flag) |
| { |
| viddec_mp4_parser_t *parser = |
| (viddec_mp4_parser_t *) &(pcontext->parser_cxt->codec_data[0]); |
| vbp_data_mp42 *query_data = (vbp_data_mp42 *) pcontext->query_data; |
| |
| vbp_picture_data_mp42 *picture_data = NULL; |
| VAPictureParameterBufferMPEG4 *picture_param = NULL; |
| |
| if (new_picture_flag) |
| { |
| query_data->number_pictures++; |
| } |
| |
| picture_data = query_data->picture_data; |
| if (picture_data == NULL || query_data->number_picture_data == 0) |
| { |
| // first entry |
| if (picture_data == NULL) |
| { |
| picture_data = vbp_malloc_set0(vbp_picture_data_mp42, 1); |
| query_data->picture_data = picture_data; |
| if (picture_data == NULL) { |
| query_data->number_picture_data = 0; |
| return; |
| } |
| } |
| query_data->number_picture_data = 1; |
| } |
| else |
| { |
| // find the last active one |
| int i = query_data->number_picture_data; |
| while (i > 1) |
| { |
| picture_data = picture_data->next_picture_data; |
| i--; |
| } |
| if (picture_data->next_picture_data == NULL) |
| { |
| picture_data->next_picture_data = vbp_malloc_set0(vbp_picture_data_mp42, 1); |
| if (picture_data->next_picture_data == NULL) { |
| return; |
| } |
| } |
| |
| query_data->number_picture_data++; |
| |
| picture_data = picture_data->next_picture_data; |
| } |
| |
| picture_param = &(picture_data->picture_param); |
| |
| uint8 idx = 0; |
| |
| picture_data->new_picture_flag = new_picture_flag; |
| |
| picture_data->vop_coded |
| = parser->info.VisualObject.VideoObject.VideoObjectPlane.vop_coded; |
| |
| |
| |
| picture_data->vop_time_increment = |
| parser->info.VisualObject.VideoObject.VideoObjectPlane.vop_time_increment; |
| |
| // fill picture_param |
| |
| |
| /* |
| * NOTE: for short video header, the parser saves vop_width and vop_height |
| * to VOL->video_object_layer_width and VOL->video_object_layer_height |
| */ |
| picture_param->vop_width |
| = parser->info.VisualObject.VideoObject.video_object_layer_width; |
| picture_param->vop_height |
| = parser->info.VisualObject.VideoObject.video_object_layer_height; |
| |
| picture_param->forward_reference_picture = VA_INVALID_SURFACE; |
| picture_param->backward_reference_picture = VA_INVALID_SURFACE; |
| |
| // Fill VAPictureParameterBufferMPEG4::vol_fields |
| |
| picture_param->vol_fields.bits.short_video_header |
| = parser->info.VisualObject.VideoObject.short_video_header; |
| picture_param->vol_fields.bits.chroma_format |
| = parser->info.VisualObject.VideoObject.VOLControlParameters.chroma_format; |
| |
| // TODO: find out why testsuite always set this value to be 0 |
| picture_param->vol_fields.bits.chroma_format = 0; |
| |
| picture_param->vol_fields.bits.interlaced |
| = parser->info.VisualObject.VideoObject.interlaced; |
| picture_param->vol_fields.bits.obmc_disable |
| = parser->info.VisualObject.VideoObject.obmc_disable; |
| picture_param->vol_fields.bits.sprite_enable |
| = parser->info.VisualObject.VideoObject.sprite_enable; |
| picture_param->vol_fields.bits.sprite_warping_accuracy |
| = parser->info.VisualObject.VideoObject.sprite_info.sprite_warping_accuracy; |
| picture_param->vol_fields.bits.quant_type |
| = parser->info.VisualObject.VideoObject.quant_type; |
| picture_param->vol_fields.bits.quarter_sample |
| = parser->info.VisualObject.VideoObject.quarter_sample; |
| picture_param->vol_fields.bits.data_partitioned |
| = parser->info.VisualObject.VideoObject.data_partitioned; |
| picture_param->vol_fields.bits.reversible_vlc |
| = parser->info.VisualObject.VideoObject.reversible_vlc; |
| picture_param->vol_fields.bits.resync_marker_disable |
| = parser->info.VisualObject.VideoObject.resync_marker_disable; |
| picture_param->no_of_sprite_warping_points |
| = parser->info.VisualObject.VideoObject.sprite_info.no_of_sprite_warping_points; |
| |
| for (idx = 0; idx < 3; idx++) |
| { |
| picture_param->sprite_trajectory_du[idx] |
| = parser->info.VisualObject.VideoObject.VideoObjectPlane.warping_mv_code_du[idx]; |
| picture_param->sprite_trajectory_dv[idx] |
| = parser->info.VisualObject.VideoObject.VideoObjectPlane.warping_mv_code_dv[idx]; |
| } |
| |
| picture_param->quant_precision |
| = parser->info.VisualObject.VideoObject.quant_precision; |
| |
| // fill VAPictureParameterBufferMPEG4::vop_fields |
| |
| |
| if (!parser->info.VisualObject.VideoObject.short_video_header) |
| { |
| picture_param->vop_fields.bits.vop_coding_type |
| = parser->info.VisualObject.VideoObject.VideoObjectPlane.vop_coding_type; |
| } |
| else |
| { |
| picture_param->vop_fields.bits.vop_coding_type |
| = parser->info.VisualObject.VideoObject.VideoObjectPlaneH263.picture_coding_type; |
| } |
| |
| // TODO: fill picture_param->vop_fields.bits.backward_reference_vop_coding_type |
| // This shall be done in mixvideoformat_mp42. See M42 spec 7.6.7 |
| |
| if (picture_param->vop_fields.bits.vop_coding_type != MP4_VOP_TYPE_B) |
| { |
| picture_param->vop_fields.bits.backward_reference_vop_coding_type |
| = picture_param->vop_fields.bits.vop_coding_type; |
| } |
| |
| picture_param->vop_fields.bits.vop_rounding_type |
| = parser->info.VisualObject.VideoObject.VideoObjectPlane.vop_rounding_type; |
| picture_param->vop_fields.bits.intra_dc_vlc_thr |
| = parser->info.VisualObject.VideoObject.VideoObjectPlane.intra_dc_vlc_thr; |
| picture_param->vop_fields.bits.top_field_first |
| = parser->info.VisualObject.VideoObject.VideoObjectPlane.top_field_first; |
| picture_param->vop_fields.bits.alternate_vertical_scan_flag |
| = parser->info.VisualObject.VideoObject.VideoObjectPlane.alternate_vertical_scan_flag; |
| |
| picture_param->vop_fcode_forward |
| = parser->info.VisualObject.VideoObject.VideoObjectPlane.vop_fcode_forward; |
| picture_param->vop_fcode_backward |
| = parser->info.VisualObject.VideoObject.VideoObjectPlane.vop_fcode_backward; |
| picture_param->vop_time_increment_resolution |
| = parser->info.VisualObject.VideoObject.vop_time_increment_resolution; |
| |
| // short header related |
| picture_param->num_gobs_in_vop |
| = parser->info.VisualObject.VideoObject.VideoObjectPlaneH263.num_gobs_in_vop; |
| picture_param->num_macroblocks_in_gob |
| = parser->info.VisualObject.VideoObject.VideoObjectPlaneH263.num_macroblocks_in_gob; |
| |
| // for direct mode prediction |
| picture_param->TRB = parser->info.VisualObject.VideoObject.TRB; |
| picture_param->TRD = parser->info.VisualObject.VideoObject.TRD; |
| } |
| |
| void vbp_fill_iq_matrix_buffer(vbp_context *pcontext) |
| { |
| viddec_mp4_parser_t *parser = |
| (viddec_mp4_parser_t *) &(pcontext->parser_cxt->codec_data[0]); |
| vbp_data_mp42 *query_data = (vbp_data_mp42 *) pcontext->query_data; |
| |
| mp4_VOLQuant_mat_t *quant_mat_info = |
| &(parser->info.VisualObject.VideoObject.quant_mat_info); |
| |
| VAIQMatrixBufferMPEG4 *iq_matrix = NULL; |
| |
| iq_matrix = &(query_data->iq_matrix_buffer); |
| |
| iq_matrix->load_intra_quant_mat = 1; //quant_mat_info->load_intra_quant_mat; |
| iq_matrix->load_non_intra_quant_mat = 1; // = quant_mat_info->load_nonintra_quant_mat; |
| memcpy(iq_matrix->intra_quant_mat, quant_mat_info->intra_quant_mat, 64); |
| memcpy(iq_matrix->non_intra_quant_mat, quant_mat_info->nonintra_quant_mat, 64); |
| } |
| |
| |
| void vbp_on_vop_mp42(vbp_context *pcontext, int list_index) |
| { |
| vbp_fill_codec_data(pcontext); |
| vbp_fill_picture_param(pcontext, 1); |
| vbp_fill_iq_matrix_buffer(pcontext); |
| vbp_fill_slice_data(pcontext, list_index); |
| } |
| |
| void vbp_on_vop_svh_mp42(vbp_context *pcontext, int list_index) |
| { |
| vbp_fill_codec_data(pcontext); |
| vbp_fill_picture_param(pcontext, 1); |
| vbp_fill_iq_matrix_buffer(pcontext); |
| vbp_fill_slice_data(pcontext, list_index); |
| } |
| |
| /* Parse for Sc code of pattern 0x00 0x00 0xXX in the current buffer. Returns either sc found or success. |
| The conext is updated with current phase and sc_code position in the buffer. |
| |
| What is phase?: phase is a value between [0-4], we keep track of consecutive '0's with this. |
| Any time a '0' is found its incremented by 1(uptp 2) and reset to '0' if a zero not found. |
| if 0xXX code is found and current phase is 2, its changed to 3 which means we found the pattern |
| we are looking for. Its incremented to 4 once we see a byte after this pattern. |
| |
| For MP4 there are two startcode patterns LVH & SVH. LVH is same as other codecs (00 00 01), SVH |
| A.K.A H263 is (00 00 8X). So we have to look for both kind of start codes. The spec doesn't |
| explicitly say if both of them can exist in a stream? So current implemenation will assume |
| that only one of them is present in a given stream to simplify implementation. The reason it can |
| get complicated is resync marker in LVH can potentially be (00 00 8) which will cause false detect |
| of SVH start code. |
| */ |
| uint32 vbp_get_sc_pos_mp42( |
| uint8 *buf, |
| uint32 length, |
| uint32 *sc_end_pos, |
| uint8 *is_normal_sc, |
| uint8 *resync_marker, |
| const bool svh_search) |
| { |
| uint8 *ptr = buf; |
| uint32 size; |
| uint32 data_left = 0, phase = 0, ret = 0; |
| size = 0; |
| |
| data_left = length; |
| *sc_end_pos = -1; |
| |
| /* parse until there is more data and start code not found */ |
| while ((data_left > 0) && (phase < 3)) |
| { |
| /* Check if we are byte aligned & phase=0, if thats the case we can check |
| work at a time instead of byte*/ |
| if (((((uint32) ptr) & 0x3) == 0) && (phase == 0)) |
| { |
| while (data_left > 3) |
| { |
| uint32 data; |
| char mask1 = 0, mask2 = 0; |
| |
| data = *((uint32 *) ptr); |
| #ifndef MFDBIGENDIAN |
| data = SWAP_WORD(data); |
| #endif |
| mask1 = (FIRST_STARTCODE_BYTE != (data & SC_BYTE_MASK0)); |
| mask2 = (FIRST_STARTCODE_BYTE != (data & SC_BYTE_MASK1)); |
| /* If second byte and fourth byte are not zero's then we cannot have a start code here as we need |
| two consecutive zero bytes for a start code pattern */ |
| if (mask1 && mask2) |
| { |
| /* Success so skip 4 bytes and start over */ |
| ptr += 4; |
| size += 4; |
| data_left -= 4; |
| continue; |
| } |
| else |
| { |
| break; |
| } |
| } |
| } |
| |
| /* At this point either data is not on a word boundary or phase > 0 or On a word boundary but we detected |
| two zero bytes in the word so we look one byte at a time*/ |
| if (data_left > 0) |
| { |
| if (*ptr == FIRST_STARTCODE_BYTE) |
| { |
| /* Phase can be 3 only if third start code byte is found */ |
| phase++; |
| ptr++; |
| size++; |
| data_left--; |
| if (phase > 2) |
| { |
| phase = 2; |
| |
| if ((((uint32) ptr) & 0x3) == 0) |
| { |
| while (data_left > 3) |
| { |
| if (*((uint32 *) ptr) != 0) |
| { |
| break; |
| } |
| ptr += 4; |
| size += 4; |
| data_left -= 4; |
| } |
| } |
| } |
| } |
| else |
| { |
| uint8 normal_sc = 0, short_sc = 0; |
| if (phase == 2) |
| { |
| normal_sc = (*ptr == THIRD_STARTCODE_BYTE); |
| if (svh_search) |
| { |
| short_sc = (SHORT_THIRD_STARTCODE_BYTE == (*ptr & 0xFC)); |
| } |
| *is_normal_sc = normal_sc; |
| |
| // at least 16-bit 0, may be GOB start code or |
| // resync marker. |
| *resync_marker = 1; |
| } |
| |
| if (!(normal_sc | short_sc)) |
| { |
| phase = 0; |
| } |
| else |
| { |
| /* Match for start code so update context with byte position */ |
| *sc_end_pos = size; |
| phase = 3; |
| } |
| ptr++; |
| size++; |
| data_left--; |
| } |
| } |
| } |
| if ((data_left > 0) && (phase == 3)) |
| { |
| (*sc_end_pos)++; |
| phase++; |
| ret = 1; |
| } |
| |
| // Return 1 only if phase is 4, else always return 0 |
| return ret; |
| } |
| |
| |
| uint32 vbp_macroblock_number_length_mp42(uint32 numOfMbs) |
| { |
| uint32 length = 0; |
| numOfMbs--; |
| do |
| { |
| numOfMbs >>= 1; |
| length++; |
| } |
| while (numOfMbs); |
| return length; |
| } |
| |
| uint32 vbp_parse_video_packet_header_mp42( |
| void *parent, |
| viddec_mp4_parser_t *parser_cxt, |
| uint16_t *quant_scale, |
| uint32 *macroblock_number) |
| { |
| uint32 ret = VBP_DATA; |
| mp4_Info_t *pInfo = &(parser_cxt->info); |
| mp4_VideoObjectLayer_t *vidObjLay = &(pInfo->VisualObject.VideoObject); |
| mp4_VideoObjectPlane_t *vidObjPlane = |
| &(pInfo->VisualObject.VideoObject.VideoObjectPlane); |
| |
| uint32 code = 0; |
| int32_t getbits = 0; |
| |
| uint16_t _quant_scale = 0; |
| uint32 _macroblock_number = 0; |
| uint32 header_extension_codes = 0; |
| uint8 vop_coding_type = vidObjPlane->vop_coding_type; |
| |
| if (vidObjLay->video_object_layer_shape != MP4_SHAPE_TYPE_RECTANGULAR) |
| { |
| ETRACE("VOL shape: %d is not supported",vidObjLay->video_object_layer_shape); |
| return VBP_DATA; |
| } |
| |
| do |
| { |
| // get macroblock_number |
| uint16_t mbs_x = (vidObjLay->video_object_layer_width + 15) >> 4; |
| uint16_t mbs_y = (vidObjLay->video_object_layer_height + 15) >> 4; |
| uint32 length = vbp_macroblock_number_length_mp42(mbs_x * mbs_y); |
| |
| getbits = viddec_pm_get_bits(parent, &code, length); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| |
| _macroblock_number = code; |
| |
| // quant_scale |
| if (vidObjLay->video_object_layer_shape != MP4_SHAPE_TYPE_BINARYONLY) |
| { |
| getbits = viddec_pm_get_bits(parent, &code, vidObjLay->quant_precision); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| _quant_scale = code; |
| } |
| |
| // header_extension_codes |
| if (vidObjLay->video_object_layer_shape == MP4_SHAPE_TYPE_RECTANGULAR) |
| { |
| getbits = viddec_pm_get_bits(parent, &code, 1); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| header_extension_codes = code; |
| } |
| |
| if (header_extension_codes) |
| { |
| // modulo time base |
| do |
| { |
| getbits = viddec_pm_get_bits(parent, &code, 1); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| } while (code); |
| |
| // marker_bit |
| getbits = viddec_pm_get_bits(parent, &code, 1); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| |
| // vop_time_increment |
| uint32 numbits = 0; |
| numbits = vidObjLay->vop_time_increment_resolution_bits; |
| if (numbits == 0) |
| { |
| // ?? |
| numbits = 1; |
| } |
| getbits = viddec_pm_get_bits(parent, &code, numbits); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| vidObjPlane->vop_time_increment = code; |
| |
| |
| // marker_bit |
| getbits = viddec_pm_get_bits(parent, &code, 1); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| |
| // vop_coding_type |
| getbits = viddec_pm_get_bits(parent, &code, 2); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| |
| vop_coding_type = code & 0x3; |
| vidObjPlane->vop_coding_type = vop_coding_type; |
| |
| |
| if (vidObjLay->video_object_layer_shape != MP4_SHAPE_TYPE_BINARYONLY) |
| { |
| // intra_dc_vlc_thr |
| getbits = viddec_pm_get_bits(parent, &code, 3); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| |
| vidObjPlane->intra_dc_vlc_thr = code; |
| if ((vidObjLay->sprite_enable == MP4_SPRITE_GMC) && |
| (vop_coding_type == MP4_VOP_TYPE_S) && |
| (vidObjLay->sprite_info.no_of_sprite_warping_points> 0)) |
| { |
| if (vbp_sprite_trajectory_mp42(parent, vidObjLay, vidObjPlane) != VBP_OK) |
| { |
| break; |
| } |
| } |
| |
| if (vidObjLay->reduced_resolution_vop_enable && |
| (vidObjLay->video_object_layer_shape == MP4_SHAPE_TYPE_RECTANGULAR) && |
| ((vop_coding_type == MP4_VOP_TYPE_I) || |
| (vop_coding_type == MP4_VOP_TYPE_P))) |
| { |
| // vop_reduced_resolution |
| getbits = viddec_pm_get_bits(parent, &code, 1); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| } |
| |
| if (vop_coding_type != MP4_VOP_TYPE_I) |
| { |
| // vop_fcode_forward |
| getbits = viddec_pm_get_bits(parent, &code, 3); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| vidObjPlane->vop_fcode_forward = code; |
| } |
| |
| if (vop_coding_type == MP4_VOP_TYPE_B) |
| { |
| // vop_fcode_backward |
| getbits = viddec_pm_get_bits(parent, &code, 3); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| vidObjPlane->vop_fcode_backward = code; |
| } |
| } |
| } |
| |
| if (vidObjLay->newpred_enable) |
| { |
| // New pred mode not supported in HW, but, does libva support this? |
| ETRACE("New pred mode not supported in HW"); |
| ret = VBP_DATA; |
| break; |
| } |
| |
| *quant_scale = _quant_scale; |
| *macroblock_number = _macroblock_number; |
| |
| ret = VBP_OK; |
| } |
| while (0); |
| return ret; |
| } |
| |
| uint32 vbp_resync_marker_Length_mp42(viddec_mp4_parser_t *parser_cxt) |
| { |
| mp4_Info_t *pInfo = &(parser_cxt->info); |
| mp4_VideoObjectPlane_t *vidObjPlane = |
| &(pInfo->VisualObject.VideoObject.VideoObjectPlane); |
| |
| uint32 resync_marker_length = 0; |
| if (vidObjPlane->vop_coding_type == MP4_VOP_TYPE_I) |
| { |
| resync_marker_length = 17; |
| } |
| else if (vidObjPlane->vop_coding_type == MP4_VOP_TYPE_B) |
| { |
| uint8 fcode_max = vidObjPlane->vop_fcode_forward; |
| if (fcode_max < vidObjPlane->vop_fcode_backward) |
| { |
| fcode_max = vidObjPlane->vop_fcode_backward; |
| } |
| resync_marker_length = 16 + fcode_max; |
| |
| // resync_marker is max(15+fcode,17) zeros followed by a one |
| if (resync_marker_length < 18) |
| resync_marker_length = 18; |
| } |
| else |
| { |
| resync_marker_length = 16 + vidObjPlane->vop_fcode_forward; |
| } |
| return resync_marker_length; |
| } |
| |
| uint32 vbp_process_slices_svh_mp42(vbp_context *pcontext, int list_index) |
| { |
| uint32 ret = VBP_OK; |
| |
| vbp_data_mp42 *query_data = (vbp_data_mp42 *) pcontext->query_data; |
| viddec_pm_cxt_t *parent = pcontext->parser_cxt; |
| viddec_mp4_parser_t *parser_cxt = |
| (viddec_mp4_parser_t *) &(parent->codec_data[0]); |
| |
| vbp_picture_data_mp42 *picture_data = vbp_get_mp42_picture_data(query_data); |
| vbp_slice_data_mp42 *slice_data = &(picture_data->slice_data); |
| VASliceParameterBufferMPEG4* slice_param = &(slice_data->slice_param); |
| |
| uint8 is_emul = 0; |
| uint32 bit_offset = 0; |
| uint32 byte_offset = 0; |
| |
| // The offsets are relative to parent->parse_cubby.buf |
| viddec_pm_get_au_pos(parent, &bit_offset, &byte_offset, &is_emul); |
| |
| slice_data->buffer_addr = parent->parse_cubby.buf; |
| |
| slice_data->slice_offset = |
| byte_offset + parent->list.data[list_index].stpos; |
| slice_data->slice_size = |
| parent->list.data[list_index].edpos - parent->list.data[list_index].stpos - byte_offset; |
| |
| slice_param->slice_data_size = slice_data->slice_size; |
| slice_param->slice_data_flag = VA_SLICE_DATA_FLAG_ALL; |
| slice_param->slice_data_offset = 0; |
| slice_param->macroblock_offset = bit_offset; |
| slice_param->macroblock_number = 0; |
| slice_param->quant_scale |
| = parser_cxt->info.VisualObject.VideoObject.VideoObjectPlaneH263.vop_quant; |
| |
| return ret; |
| } |
| #define SEARCH_SYNC_OPT |
| uint32 vbp_process_slices_mp42(vbp_context *pcontext, int list_index) |
| { |
| vbp_data_mp42 *query_data = (vbp_data_mp42 *) pcontext->query_data; |
| viddec_pm_cxt_t *parent = pcontext->parser_cxt; |
| viddec_mp4_parser_t *parser_cxt = (viddec_mp4_parser_t *) &(parent->codec_data[0]); |
| |
| vbp_picture_data_mp42 *picture_data = NULL; |
| vbp_slice_data_mp42 *slice_data = NULL; |
| VASliceParameterBufferMPEG4* slice_param = NULL; |
| |
| uint32 ret = VBP_OK; |
| |
| uint8 is_emul = 0; |
| uint32 bit_offset = 0; |
| uint32 byte_offset = 0; |
| |
| uint32 code = 0; |
| int32_t getbits = 0; |
| uint32 resync_marker_length = 0; |
| |
| /* The offsets are relative to parent->parse_cubby.buf */ |
| viddec_pm_get_au_pos(parent, &bit_offset, &byte_offset, &is_emul); |
| |
| picture_data = vbp_get_mp42_picture_data(query_data); |
| slice_data = &(picture_data->slice_data); |
| slice_param = &(slice_data->slice_param); |
| |
| slice_data->buffer_addr = parent->parse_cubby.buf; |
| |
| slice_data->slice_offset = byte_offset + parent->list.data[list_index].stpos; |
| slice_data->slice_size = |
| parent->list.data[list_index].edpos - parent->list.data[list_index].stpos - byte_offset; |
| |
| slice_param->slice_data_size = slice_data->slice_size; |
| slice_param->slice_data_flag = VA_SLICE_DATA_FLAG_ALL; |
| slice_param->slice_data_offset = 0; |
| slice_param->macroblock_offset = bit_offset; |
| slice_param->macroblock_number = 0; |
| slice_param->quant_scale |
| = parser_cxt->info.VisualObject.VideoObject.VideoObjectPlane.vop_quant; |
| |
| if (parser_cxt->info.VisualObject.VideoObject.resync_marker_disable) |
| { |
| // no resync_marker |
| VTRACE("resync marker is disabled"); |
| return VBP_OK; |
| } |
| |
| // scan for resync_marker |
| viddec_pm_get_au_pos(parent, &bit_offset, &byte_offset, &is_emul); |
| if (bit_offset) |
| { |
| // byte-aligned |
| getbits = viddec_pm_get_bits(parent, &code, 8 - bit_offset); |
| if (getbits == -1) |
| { |
| WTRACE("FAILURE!!!! getbits %s : %d", __FUNCTION__, __LINE__); |
| return VBP_DATA; |
| } |
| } |
| |
| // get resync_marker_length |
| resync_marker_length = vbp_resync_marker_Length_mp42(parser_cxt); |
| |
| uint16_t quant_scale = 0; |
| uint32 macroblock_number = 0; |
| |
| while (1) |
| { |
| #ifndef SEARCH_SYNC_OPT |
| getbits = viddec_pm_peek_bits(parent, &code, resync_marker_length); |
| |
| // return VBP_OK as resync_marker may not be present |
| BREAK_GETBITS_FAIL(getbits, ret); |
| |
| if (code != 1) |
| { |
| getbits = viddec_pm_get_bits(parent, &code, 8); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| continue; |
| } |
| #else |
| |
| // read 3 bytes since resync_marker_length is between 17 bits and 23 bits |
| if (parent->getbits.bstrm_buf.buf_index + 3 > parent->getbits.bstrm_buf.buf_end) |
| { |
| break; |
| } |
| |
| code = parent->getbits.bstrm_buf.buf[parent->getbits.bstrm_buf.buf_index] << 16 | |
| parent->getbits.bstrm_buf.buf[parent->getbits.bstrm_buf.buf_index+1] << 8 | |
| parent->getbits.bstrm_buf.buf[parent->getbits.bstrm_buf.buf_index+2]; |
| |
| if (code >> (24-resync_marker_length) != 1) |
| { |
| int byte0 = code & 0xff; |
| int byte1 = (code >> 8) & 0xff; |
| if (byte0 != 0) |
| { |
| parent->getbits.bstrm_buf.buf_index += 3; |
| } |
| else if (byte1 != 0) |
| { |
| parent->getbits.bstrm_buf.buf_index += 2; |
| } |
| else |
| { |
| parent->getbits.bstrm_buf.buf_index += 1; |
| } |
| continue; |
| } |
| #endif |
| // We found resync_marker |
| viddec_pm_get_au_pos(parent, &bit_offset, &byte_offset, &is_emul); |
| |
| // update slice data as we found resync_marker |
| slice_data->slice_size -= |
| (parent->list.data[list_index].edpos - parent->list.data[list_index].stpos - byte_offset); |
| slice_param->slice_data_size = slice_data->slice_size; |
| |
| // skip resync marker |
| getbits = viddec_pm_get_bits(parent, &code, resync_marker_length); |
| |
| // return VBP_DATA, this should never happen! |
| BREAK_GETBITS_FAIL(getbits, ret); |
| |
| // parse video_packet_header |
| ret = vbp_parse_video_packet_header_mp42(parent, parser_cxt, |
| &quant_scale, ¯oblock_number); |
| |
| if (ret != VBP_OK) |
| { |
| ETRACE("Failed to parse video packet header.\n"); |
| return ret; |
| } |
| |
| // new_picture_flag = 0, this is not the first slice of a picture |
| vbp_fill_picture_param(pcontext, 0); |
| |
| picture_data = vbp_get_mp42_picture_data(query_data); |
| slice_data = &(picture_data->slice_data); |
| slice_param = &(slice_data->slice_param); |
| |
| |
| viddec_pm_get_au_pos(parent, &bit_offset, &byte_offset, &is_emul); |
| |
| slice_data->buffer_addr = parent->parse_cubby.buf; |
| |
| slice_data->slice_offset = |
| byte_offset + parent->list.data[list_index].stpos; |
| slice_data->slice_size = |
| parent->list.data[list_index].edpos - parent->list.data[list_index].stpos - byte_offset; |
| |
| slice_param->slice_data_size = slice_data->slice_size; |
| slice_param->slice_data_flag = VA_SLICE_DATA_FLAG_ALL; |
| slice_param->slice_data_offset = 0; |
| slice_param->macroblock_offset = bit_offset; |
| slice_param->macroblock_number = macroblock_number; |
| slice_param->quant_scale = quant_scale; |
| |
| if (bit_offset) |
| { |
| // byte-align parsing position |
| getbits = viddec_pm_skip_bits(parent, 8 - bit_offset); |
| if (getbits == -1) |
| { |
| ETRACE("Failed to align parser to byte position.\n"); |
| return VBP_DATA; |
| } |
| } |
| |
| } |
| |
| return VBP_OK; |
| } |
| |
| uint32 vbp_process_video_packet_mp42(vbp_context *pcontext) |
| { |
| vbp_data_mp42 *query_data = (vbp_data_mp42 *) pcontext->query_data; |
| viddec_pm_cxt_t *parent = pcontext->parser_cxt; |
| viddec_mp4_parser_t *parser_cxt = (viddec_mp4_parser_t *) &(parent->codec_data[0]); |
| uint32 code = 0; |
| int32_t getbits = 0; |
| |
| uint32 ret = VBP_DATA; |
| |
| |
| // setup bitstream parser |
| parent->getbits.list = &(parent->list); |
| |
| parent->getbits.bstrm_buf.buf = parent->parse_cubby.buf; |
| parent->getbits.bstrm_buf.buf_index = 0; |
| parent->getbits.bstrm_buf.buf_st = 0; |
| parent->getbits.bstrm_buf.buf_end = parent->parse_cubby.size; |
| parent->getbits.bstrm_buf.buf_bitoff = 0; |
| |
| parent->getbits.au_pos = 0; |
| parent->getbits.list_off = 0; |
| parent->getbits.phase = 0; |
| parent->getbits.emulation_byte_counter = 0; |
| |
| parent->list.start_offset = 0; |
| parent->list.end_offset = parent->parse_cubby.size; |
| parent->list.total_bytes = parent->parse_cubby.size; |
| |
| |
| // skip leading zero-byte |
| while (code == 0) |
| { |
| getbits = viddec_pm_get_bits(parent, &code, 8); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| getbits = viddec_pm_peek_bits(parent, &code, 8); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| } |
| |
| if (getbits != 0) |
| { |
| return VBP_DATA; |
| } |
| |
| // resync-marker is represented as 17-23 bits. (16-22 bits of 0) |
| // as 16-bit '0' has been skipped, we try to parse buffer bit by bit |
| // until bit 1 is encounted or up to 7 bits are parsed. |
| code = 0; |
| uint8 count = 0; |
| while (code == 0 && count < 7) |
| { |
| getbits = viddec_pm_get_bits(parent, &code, 1); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| count++; |
| } |
| |
| if (code == 0 || getbits != 0) |
| { |
| ETRACE("no resync-marker in the buffer.\n"); |
| return ret; |
| } |
| |
| // resync marker is skipped |
| uint16_t quant_scale = 0; |
| uint32 macroblock_number = 0; |
| |
| // parse video_packet_header |
| vbp_parse_video_packet_header_mp42(parent, parser_cxt, &quant_scale, ¯oblock_number); |
| |
| // new_picture_flag = 0, this is not the first slice of a picture |
| vbp_fill_picture_param(pcontext, 0); |
| |
| vbp_picture_data_mp42 *picture_data = NULL; |
| vbp_slice_data_mp42 *slice_data = NULL; |
| VASliceParameterBufferMPEG4* slice_param = NULL; |
| |
| picture_data = vbp_get_mp42_picture_data(query_data); |
| slice_data = &(picture_data->slice_data); |
| slice_param = &(slice_data->slice_param); |
| |
| ret = vbp_process_slices_mp42(pcontext, 0); |
| |
| // update slice's QP and macro_block number as it is set to 0 by default. |
| slice_param->macroblock_number = macroblock_number; |
| slice_param->quant_scale = quant_scale; |
| |
| // VOP must be coded! |
| picture_data->vop_coded = 1; |
| return ret; |
| |
| } |
| |
| |
| static inline uint32 vbp_sprite_dmv_length_mp42( |
| void * parent, |
| int32_t *dmv_length) |
| { |
| uint32 code, skip; |
| int32_t getbits = 0; |
| uint32 ret = VBP_DATA; |
| *dmv_length = 0; |
| skip = 3; |
| do |
| { |
| getbits = viddec_pm_peek_bits(parent, &code, skip); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| |
| if (code == 7) |
| { |
| viddec_pm_skip_bits(parent, skip); |
| getbits = viddec_pm_peek_bits(parent, &code, 9); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| |
| skip = 1; |
| while ((code & 256) != 0) |
| { |
| // count number of 1 bits |
| code <<= 1; |
| skip++; |
| } |
| *dmv_length = 5 + skip; |
| } |
| else |
| { |
| skip = (code <= 1) ? 2 : 3; |
| *dmv_length = code - 1; |
| } |
| viddec_pm_skip_bits(parent, skip); |
| ret = VBP_OK; |
| |
| } |
| while (0); |
| return ret; |
| } |
| |
| |
| static inline uint32 vbp_sprite_trajectory_mp42( |
| void *parent, |
| mp4_VideoObjectLayer_t *vidObjLay, |
| mp4_VideoObjectPlane_t *vidObjPlane) |
| { |
| uint32 code, i; |
| int32_t dmv_length = 0, dmv_code = 0, getbits = 0; |
| uint32 ret = VBP_OK; |
| for (i = 0; i < (uint32) vidObjLay->sprite_info.no_of_sprite_warping_points; i++) |
| { |
| ret = VBP_DATA; |
| ret = vbp_sprite_dmv_length_mp42(parent, &dmv_length); |
| if (ret != VBP_OK) |
| { |
| break; |
| } |
| if (dmv_length <= 0) |
| { |
| dmv_code = 0; |
| } |
| else |
| { |
| getbits = viddec_pm_get_bits(parent, &code, (uint32) dmv_length); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| dmv_code = (int32_t) code; |
| if ((dmv_code & (1 << (dmv_length - 1))) == 0) |
| { |
| dmv_code -= (1 << dmv_length) - 1; |
| } |
| } |
| getbits = viddec_pm_get_bits(parent, &code, 1); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| if (code != 1) |
| { |
| ret = VBP_DATA; |
| break; |
| } |
| vidObjPlane->warping_mv_code_du[i] = dmv_code; |
| // TODO: create another inline function to avoid code duplication |
| ret = vbp_sprite_dmv_length_mp42(parent, &dmv_length); |
| if (ret != VBP_OK) |
| { |
| break; |
| } |
| // reset return value in case early break |
| ret = VBP_DATA; |
| if (dmv_length <= 0) |
| { |
| dmv_code = 0; |
| } |
| else |
| { |
| getbits = viddec_pm_get_bits(parent, &code, (uint32) dmv_length); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| dmv_code = (int32_t) code; |
| if ((dmv_code & (1 << (dmv_length - 1))) == 0) |
| { |
| dmv_code -= (1 << dmv_length) - 1; |
| } |
| } |
| getbits = viddec_pm_get_bits(parent, &code, 1); |
| BREAK_GETBITS_FAIL(getbits, ret); |
| if (code != 1) |
| { |
| break; |
| } |
| vidObjPlane->warping_mv_code_dv[i] = dmv_code; |
| |
| // set to VBP_OK |
| ret = VBP_OK; |
| |
| } |
| return ret; |
| } |
| |
| |
| /* |
| * free memory of vbp_data_mp42 structure and its members |
| */ |
| uint32 vbp_free_query_data_mp42(vbp_context *pcontext) |
| { |
| vbp_data_mp42 *query_data = (vbp_data_mp42 *) pcontext->query_data; |
| vbp_picture_data_mp42* current = NULL; |
| vbp_picture_data_mp42* next = NULL; |
| |
| if (pcontext->parser_private) |
| { |
| free(pcontext->parser_private); |
| pcontext->parser_private = NULL; |
| } |
| if (query_data) |
| { |
| current = query_data->picture_data; |
| while (current != NULL) |
| { |
| next = current->next_picture_data; |
| free(current); |
| current = next; |
| } |
| |
| free(query_data); |
| } |
| |
| pcontext->query_data = NULL; |
| return VBP_OK; |
| } |
| |
| /* |
| * Allocate memory for vbp_data_mp42 structure and all its members. |
| */ |
| uint32 vbp_allocate_query_data_mp42(vbp_context *pcontext) |
| { |
| vbp_data_mp42 *query_data; |
| pcontext->query_data = NULL; |
| |
| query_data = vbp_malloc_set0(vbp_data_mp42, 1); |
| if (query_data == NULL) |
| { |
| goto cleanup; |
| } |
| |
| pcontext->query_data = (void *) query_data; |
| query_data->picture_data = NULL; |
| query_data->number_picture_data = 0; |
| query_data->number_pictures = 0; |
| |
| pcontext->parser_private = NULL; |
| vbp_mp42_parser_private *parser_private = NULL; |
| |
| parser_private = vbp_malloc_set0(vbp_mp42_parser_private, 1); |
| if (NULL == parser_private) |
| { |
| goto cleanup; |
| } |
| |
| /* assign the pointer */ |
| pcontext->parser_private = (void *)parser_private; |
| |
| /* init the pointer */ |
| parser_private->short_video_header = TRUE; |
| return VBP_OK; |
| |
| cleanup: |
| |
| vbp_free_query_data_mp42(pcontext); |
| |
| return VBP_MEM; |
| } |