Patch for split codec_data from first frame
[platform/core/api/mediacodec.git] / src / media_codec_bitstream.c
index e50baeb..373da79 100755 (executable)
@@ -17,6 +17,8 @@
 #include <stdio.h>
 #include <dlog.h>
 #include <media_codec_bitstream.h>
+#include <gst/base/gstbytereader.h>
+#include <gst/base/gstbitreader.h>
 
 void mc_init_bits(mc_bitstream_t *stream, unsigned char *data, int size)
 {
@@ -182,15 +184,25 @@ int __mc_decode_sps(mc_bitstream_t *pstream, int *width, int *height)
        return ret;
 }
 
+int __mc_scan_for_h264_start_codes(const guint8 * data, guint size)
+{
+       GstByteReader br;
+       gst_byte_reader_init(&br, data, size);
+
+       /* NALU not empty, so we can at least expect 1 (even 2) bytes following sc */
+       return gst_byte_reader_masked_scan_uint32(&br, 0xffffff00, 0x00000100, 0, size);
+}
+
 int _mc_check_h264_bytestream(unsigned char *nal, int byte_length, bool port, bool *codec_config, bool *sync_flag, bool *slice)
 {
-       int ret = MC_ERROR_NONE;
+       int ret = 0; /* (ret <= 0)==>>error occured;  (ret > 0)==>>codec data size */
        int stacked_length = 0;
        int nal_length = 0;
        unsigned int syntax = 0;
        unsigned int state = 0;
        int count = 0;
        int nal_unit_type = 0;
+       int codec_length = 0;
 
        mc_bitstream_t pstream;
 
@@ -211,10 +223,12 @@ int _mc_check_h264_bytestream(unsigned char *nal, int byte_length, bool port, bo
                                if ((ret = __mc_decode_sps(&pstream, NULL, NULL)) != MC_ERROR_NONE)
                                        return ret;
                                state |= MC_EXIST_SPS;
+                               codec_length += nal_length;
                                break;
                        case NAL_PICTURE_PARAMETER_SET:
                                LOGD("nal_unit_type : PPS");
                                state |= MC_EXIST_PPS;
+                               codec_length += nal_length;
                                break;
                        case NAL_SLICE_IDR:
                                LOGD("nal_unit_type : IDR");
@@ -231,6 +245,8 @@ int _mc_check_h264_bytestream(unsigned char *nal, int byte_length, bool port, bo
                        stacked_length += nal_length;
                        count++;
 
+                       LOGD("codec_data length : %d", codec_length);
+
                        if ((stacked_length >= byte_length) || count > 5)
                                break;
                }
@@ -257,7 +273,7 @@ int _mc_check_h264_bytestream(unsigned char *nal, int byte_length, bool port, bo
                *slice = CHECK_VALID_PACKET(state, MC_EXIST_SLICE) ? 1 : 0;
        }
 
-       return ret;
+       return codec_length;
 }
 
 int _mc_check_valid_h263_frame(unsigned char *p, int size)
@@ -367,3 +383,75 @@ bool _mc_check_h263_out_bytestream(unsigned char *p, int buf_length, bool* need_
        return TRUE;
 }
 
+int _mc_get_h264_codecdata_size(guint8 *data, int size)
+{
+       int offset = 0;
+       int data_size = 0;
+       bool is_bytestream = FALSE;
+
+       if ((offset = __mc_scan_for_h264_start_codes(data, size)) == -1) {
+               /*Packetized Format*/
+               is_bytestream = FALSE;
+       } else {
+               /*Byte-Stream Format*/
+               is_bytestream = TRUE;
+       }
+
+       if (is_bytestream) {
+               /*Byte-Stream Format*/
+               data_size = _mc_check_h264_bytestream(data, size, 0, NULL, NULL, NULL);
+               if (data_size <= 0) {
+                       LOGE("No valid SPS/PPS ...");
+                       return MC_INVALID_IN_BUF;
+               }
+               return data_size;
+       } else {
+               /*Packetized Format*/
+               int num_sps = 0, num_pps = 0;
+               int nalu_size = 0;
+               int i = 0;
+               unsigned int state = 0;
+               GstBitReader br;
+
+               offset = 0;
+               /* parse the avcC data */
+               if (size < 7) { /* when numSPS==0 and numPPS==0, length is 7 bytes */
+                       LOGE("If contains codec_data, size should over 7 bytes ...");
+                       return MC_INVALID_IN_BUF;
+               }
+               /* parse the version, this must be 1 */
+               if (data[0] != 1) {
+                       LOGE("If contains codec_data, first byte must be 1 ...");
+                       return MC_INVALID_IN_BUF;
+               }
+
+               num_sps = data[5] & 0x1f;
+               offset = 6;
+               for (i = 0; i < num_sps; i++) {
+                       gst_bit_reader_init(&br, data + offset, size - offset);
+                       nalu_size = gst_bit_reader_get_bits_uint32_unchecked(&br, 2 * 8);
+
+                       offset += nalu_size + 2;
+                       state |= MC_EXIST_SPS;
+               }
+
+               num_pps = data[offset];
+               offset++;
+
+               for (i = 0; i < num_pps; i++) {
+                       gst_bit_reader_init(&br, data + offset, size - offset);
+                       nalu_size = gst_bit_reader_get_bits_uint32_unchecked(&br, 2 * 8);
+
+                       offset += nalu_size + 2;
+                       state |= MC_EXIST_PPS;
+               }
+
+               if (CHECK_VALID_PACKET(state, MC_VALID_HEADER)) {
+                       LOGD("Found valid SPS/PPS data...\n");
+                       return offset;
+               }
+
+               return MC_INVALID_IN_BUF;
+       }
+
+}