summaryrefslogtreecommitdiff
path: root/mm-video-v4l2/vidc/vdec/src/mp4_utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mm-video-v4l2/vidc/vdec/src/mp4_utils.cpp')
-rw-r--r--mm-video-v4l2/vidc/vdec/src/mp4_utils.cpp302
1 files changed, 302 insertions, 0 deletions
diff --git a/mm-video-v4l2/vidc/vdec/src/mp4_utils.cpp b/mm-video-v4l2/vidc/vdec/src/mp4_utils.cpp
new file mode 100644
index 00000000..95335d08
--- /dev/null
+++ b/mm-video-v4l2/vidc/vdec/src/mp4_utils.cpp
@@ -0,0 +1,302 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010 - 2013, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of The Linux Foundation nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+#include "mp4_utils.h"
+//#include "omx_vdec.h"
+# include <stdio.h>
+#ifdef _ANDROID_
+ extern "C"{
+ #include<utils/Log.h>
+ }
+#endif//_ANDROID_
+
+#undef DEBUG_PRINT_LOW
+#undef DEBUG_PRINT_HIGH
+#undef DEBUG_PRINT_ERROR
+
+#define DEBUG_PRINT_LOW ALOGV
+#define DEBUG_PRINT_HIGH ALOGV
+#define DEBUG_PRINT_ERROR ALOGE
+
+MP4_Utils::MP4_Utils()
+{
+ m_SrcWidth = 0;
+ m_SrcHeight = 0;
+ vop_time_resolution = 0;
+ vop_time_found = false;
+
+}
+MP4_Utils::~MP4_Utils()
+{
+}
+
+uint32 MP4_Utils::read_bit_field(posInfoType * posPtr, uint32 size) {
+ uint8 *bits = &posPtr->bytePtr[0];
+ uint32 bitBuf =
+ (bits[0] << 24) | (bits[1] << 16) | (bits[2] << 8) | bits[3];
+
+ uint32 value = (bitBuf >> (32 - posPtr->bitPos - size)) & MASK(size);
+
+ /* Update the offset in preparation for next field */
+ posPtr->bitPos += size;
+
+ while (posPtr->bitPos >= 8) {
+ posPtr->bitPos -= 8;
+ posPtr->bytePtr++;
+ }
+ return value;
+}
+static uint8 *find_code
+ (uint8 * bytePtr, uint32 size, uint32 codeMask, uint32 referenceCode) {
+ uint32 code = 0xFFFFFFFF;
+ for (uint32 i = 0; i < size; i++) {
+ code <<= 8;
+ code |= *bytePtr++;
+
+ if ((code & codeMask) == referenceCode) {
+ return bytePtr;
+ }
+ }
+
+ DEBUG_PRINT_LOW("Unable to find code 0x%x\n", referenceCode);
+ return NULL;
+}
+bool MP4_Utils::parseHeader(mp4StreamType * psBits) {
+ uint32 profile_and_level_indication = 0;
+ uint8 VerID = 1; /* default value */
+ long hxw = 0;
+
+ m_posInfo.bitPos = 0;
+ m_posInfo.bytePtr = psBits->data;
+ m_dataBeginPtr = psBits->data;
+
+ m_posInfo.bytePtr = find_code(m_posInfo.bytePtr,4,
+ MASK(32),VOP_START_CODE);
+ if(m_posInfo.bytePtr) {
+ return false;
+ }
+
+ m_posInfo.bitPos = 0;
+ m_posInfo.bytePtr = psBits->data;
+ m_dataBeginPtr = psBits->data;
+ m_posInfo.bytePtr = find_code(m_posInfo.bytePtr,4,
+ MASK(32),GOV_START_CODE);
+ if(m_posInfo.bytePtr) {
+ return false;
+ }
+
+ m_posInfo.bitPos = 0;
+ m_posInfo.bytePtr = psBits->data;
+ m_dataBeginPtr = psBits->data;
+ /* parsing Visual Object Seqence(VOS) header */
+ m_posInfo.bytePtr = find_code(m_posInfo.bytePtr,
+ psBits->numBytes,
+ MASK(32),
+ VISUAL_OBJECT_SEQUENCE_START_CODE);
+ if ( m_posInfo.bytePtr == NULL ){
+ m_posInfo.bitPos = 0;
+ m_posInfo.bytePtr = psBits->data;
+ }
+ else {
+ uint32 profile_and_level_indication = read_bit_field (&m_posInfo, 8);
+ }
+ /* parsing Visual Object(VO) header*/
+ /* note: for now, we skip over the user_data */
+ m_posInfo.bytePtr = find_code(m_posInfo.bytePtr,psBits->numBytes,
+ MASK(32),VISUAL_OBJECT_START_CODE);
+ if(m_posInfo.bytePtr == NULL) {
+ m_posInfo.bitPos = 0;
+ m_posInfo.bytePtr = psBits->data;
+ }
+ else {
+ uint32 is_visual_object_identifier = read_bit_field (&m_posInfo, 1);
+ if ( is_visual_object_identifier ) {
+ /* visual_object_verid*/
+ read_bit_field (&m_posInfo, 4);
+ /* visual_object_priority*/
+ read_bit_field (&m_posInfo, 3);
+ }
+
+ /* visual_object_type*/
+ uint32 visual_object_type = read_bit_field (&m_posInfo, 4);
+ if ( visual_object_type != VISUAL_OBJECT_TYPE_VIDEO_ID ) {
+ return false;
+ }
+ /* skipping video_signal_type params*/
+ /*parsing Video Object header*/
+ m_posInfo.bytePtr = find_code(m_posInfo.bytePtr,psBits->numBytes,
+ VIDEO_OBJECT_START_CODE_MASK,VIDEO_OBJECT_START_CODE);
+ if ( m_posInfo.bytePtr == NULL ) {
+ return false;
+ }
+ }
+
+ /* parsing Video Object Layer(VOL) header */
+ m_posInfo.bitPos = 0;
+ m_posInfo.bytePtr = find_code(m_posInfo.bytePtr,
+ psBits->numBytes,
+ VIDEO_OBJECT_LAYER_START_CODE_MASK,
+ VIDEO_OBJECT_LAYER_START_CODE);
+ if ( m_posInfo.bytePtr == NULL ) {
+ m_posInfo.bitPos = 0;
+ m_posInfo.bytePtr = psBits->data;
+ }
+
+ // 1 -> random accessible VOL
+ read_bit_field(&m_posInfo, 1);
+
+ uint32 video_object_type_indication = read_bit_field (&m_posInfo, 8);
+ if ( (video_object_type_indication != SIMPLE_OBJECT_TYPE) &&
+ (video_object_type_indication != SIMPLE_SCALABLE_OBJECT_TYPE) &&
+ (video_object_type_indication != CORE_OBJECT_TYPE) &&
+ (video_object_type_indication != ADVANCED_SIMPLE) &&
+ (video_object_type_indication != RESERVED_OBJECT_TYPE) &&
+ (video_object_type_indication != MAIN_OBJECT_TYPE)) {
+ return false;
+ }
+ /* is_object_layer_identifier*/
+ uint32 is_object_layer_identifier = read_bit_field (&m_posInfo, 1);
+ if (is_object_layer_identifier) {
+ uint32 video_object_layer_verid = read_bit_field (&m_posInfo, 4);
+ uint32 video_object_layer_priority = read_bit_field (&m_posInfo, 3);
+ VerID = (unsigned char)video_object_layer_verid;
+ }
+
+ /* aspect_ratio_info*/
+ uint32 aspect_ratio_info = read_bit_field (&m_posInfo, 4);
+ if ( aspect_ratio_info == EXTENDED_PAR ) {
+ /* par_width*/
+ read_bit_field (&m_posInfo, 8);
+ /* par_height*/
+ read_bit_field (&m_posInfo, 8);
+ }
+ /* vol_control_parameters */
+ uint32 vol_control_parameters = read_bit_field (&m_posInfo, 1);
+ if ( vol_control_parameters ) {
+ /* chroma_format*/
+ uint32 chroma_format = read_bit_field (&m_posInfo, 2);
+ if ( chroma_format != 1 ) {
+ return false;
+ }
+ /* low_delay*/
+ uint32 low_delay = read_bit_field (&m_posInfo, 1);
+ /* vbv_parameters (annex D)*/
+ uint32 vbv_parameters = read_bit_field (&m_posInfo, 1);
+ if ( vbv_parameters ) {
+ /* first_half_bitrate*/
+ uint32 first_half_bitrate = read_bit_field (&m_posInfo, 15);
+ uint32 marker_bit = read_bit_field (&m_posInfo, 1);
+ if ( marker_bit != 1) {
+ return false;
+ }
+ /* latter_half_bitrate*/
+ uint32 latter_half_bitrate = read_bit_field (&m_posInfo, 15);
+ marker_bit = read_bit_field (&m_posInfo, 1);
+ if ( marker_bit != 1) {
+ return false;
+ }
+ uint32 VBVPeakBitRate = (first_half_bitrate << 15) + latter_half_bitrate;
+ /* first_half_vbv_buffer_size*/
+ uint32 first_half_vbv_buffer_size = read_bit_field (&m_posInfo, 15);
+ marker_bit = read_bit_field (&m_posInfo, 1);
+ if ( marker_bit != 1) {
+ return false;
+ }
+ /* latter_half_vbv_buffer_size*/
+ uint32 latter_half_vbv_buffer_size = read_bit_field (&m_posInfo, 3);
+ uint32 VBVBufferSize = (first_half_vbv_buffer_size << 3) + latter_half_vbv_buffer_size;
+ /* first_half_vbv_occupancy*/
+ uint32 first_half_vbv_occupancy = read_bit_field (&m_posInfo, 11);
+ marker_bit = read_bit_field (&m_posInfo, 1);
+ if ( marker_bit != 1) {
+ return false;
+ }
+ /* latter_half_vbv_occupancy*/
+ uint32 latter_half_vbv_occupancy = read_bit_field (&m_posInfo, 15);
+ marker_bit = read_bit_field (&m_posInfo, 1);
+ if ( marker_bit != 1) {
+ return false;
+ }
+ }/* vbv_parameters*/
+ }/*vol_control_parameters*/
+
+ /* video_object_layer_shape*/
+ uint32 video_object_layer_shape = read_bit_field (&m_posInfo, 2);
+ uint8 VOLShape = (unsigned char)video_object_layer_shape;
+ if ( VOLShape != MPEG4_SHAPE_RECTANGULAR ) {
+ return false;
+ }
+ /* marker_bit*/
+ uint32 marker_bit = read_bit_field (&m_posInfo, 1);
+ if ( marker_bit != 1 ) {
+ return false;
+ }
+ /* vop_time_increment_resolution*/
+ uint32 vop_time_increment_resolution = read_bit_field (&m_posInfo, 16);
+ vop_time_resolution = vop_time_increment_resolution;
+ vop_time_found = true;
+ return true;
+}
+
+bool MP4_Utils::is_notcodec_vop(unsigned char *pbuffer, unsigned int len)
+{
+ unsigned int index = 4,vop_bits=0;
+ unsigned int temp = vop_time_resolution - 1;
+ unsigned char vop_type=0,modulo_bit=0,not_coded=0;
+ if (!vop_time_found || !pbuffer || len < 5) {
+ return false;
+ }
+ if((pbuffer[0] == 0) && (pbuffer[1] == 0) && (pbuffer[2] == 1) && (pbuffer[3] == 0xB6)){
+ while(temp) {
+ vop_bits++;
+ temp >>= 1;
+ }
+ vop_type = (pbuffer[index] & 0xc0) >> 6;
+ unsigned bits_parsed = 2;
+ do {
+ modulo_bit = pbuffer[index] & (1 << (7-bits_parsed));
+ bits_parsed++;
+ index += bits_parsed/8;
+ bits_parsed = bits_parsed %8;
+ if(index >= len) {
+ return false;
+ }
+ }while(modulo_bit);
+ bits_parsed++; //skip marker bit
+ bits_parsed += vop_bits + 1;//Vop bit & Marker bits
+ index += bits_parsed/8;
+ if(index >= len) {
+ return false;
+ }
+ bits_parsed = bits_parsed % 8;
+ not_coded = pbuffer[index] & (1 << (7 - bits_parsed));
+ if(!not_coded){
+ return true;
+ }
+ }
+ return false;
+}