h264_nal: Support resuming bitstream format conversion across buffers
authorMartin Storsjö <martin@martin.st>
Mon, 18 Mar 2013 19:39:20 +0000 (21:39 +0200)
committerMartin Storsjö <martin@martin.st>
Mon, 18 Mar 2013 20:07:02 +0000 (22:07 +0200)
This is necessary in order to pass one single H264 packet in
multiple OMX buffers to the decoder.

Signed-off-by: Martin Storsjö <martin@martin.st>
modules/codec/h264_nal.h
modules/codec/omxil/android_mediacodec.c
modules/codec/omxil/omxil.c

index ed9f6ae..7fd3526 100644 (file)
@@ -99,24 +99,46 @@ static int convert_sps_pps( decoder_t *p_dec, const uint8_t *p_buf,
 }
 
 /* Convert H.264 NAL format to annex b in-place */
+struct H264ConvertState {
+    uint32_t nal_len;
+    uint32_t nal_pos;
+};
+
 static void convert_h264_to_annexb( uint8_t *p_buf, uint32_t i_len,
-                                    size_t i_nal_size )
+                                    size_t i_nal_size,
+                                    struct H264ConvertState *state )
 {
     if( i_nal_size < 3 || i_nal_size > 4 )
         return;
 
     /* This only works for NAL sizes 3-4 */
-    while( i_len >= i_nal_size )
+    while( i_len > 0 )
     {
-        uint32_t nal_len = 0;
-        for( unsigned int i = 0; i < i_nal_size; i++ ) {
-            nal_len = (nal_len << 8) | p_buf[i];
-            p_buf[i] = 0;
+        if( state->nal_pos < i_nal_size ) {
+            unsigned int i;
+            for( i = 0; state->nal_pos < i_nal_size && i < i_len; i++, state->nal_pos++ ) {
+                state->nal_len = (state->nal_len << 8) | p_buf[i];
+                p_buf[i] = 0;
+            }
+            if( state->nal_pos < i_nal_size )
+                return;
+            p_buf[i - 1] = 1;
+            p_buf += i;
+            i_len -= i;
+        }
+        if( state->nal_len > INT_MAX )
+            return;
+        if( state->nal_len > i_len )
+        {
+            state->nal_len -= i_len;
+            return;
+        }
+        else
+        {
+            p_buf += state->nal_len;
+            i_len -= state->nal_len;
+            state->nal_len = 0;
+            state->nal_pos = 0;
         }
-        p_buf[i_nal_size - 1] = 1;
-        if( nal_len > INT_MAX || nal_len + i_nal_size > (unsigned int) i_len )
-            break;
-        p_buf += nal_len + i_nal_size;
-        i_len -= nal_len + i_nal_size;
     }
 }
index c3c7095..dd9171e 100644 (file)
@@ -495,6 +495,7 @@ static picture_t *DecodeVideo(decoder_t *p_dec, block_t **pp_block)
     decoder_sys_t *p_sys = p_dec->p_sys;
     picture_t *p_pic = NULL;
     JNIEnv *env = NULL;
+    struct H264ConvertState convert_state = { 0, 0 };
 
     if (!pp_block || !*pp_block)
         return NULL;
@@ -527,7 +528,7 @@ static picture_t *DecodeVideo(decoder_t *p_dec, block_t **pp_block)
             size = p_block->i_buffer;
         memcpy(bufptr, p_block->p_buffer, size);
 
-        convert_h264_to_annexb(bufptr, size, p_sys->nal_size);
+        convert_h264_to_annexb(bufptr, size, p_sys->nal_size, &convert_state);
 
         int64_t ts = p_block->i_pts;
         if (!ts && p_block->i_dts)
index bcc2684..eff2375 100644 (file)
@@ -1135,6 +1135,7 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
     OMX_BUFFERHEADERTYPE *p_header;
     block_t *p_block;
     int i_input_used = 0;
+    struct H264ConvertState convert_state = { 0, 0 };
 
     if( !pp_block || !*pp_block )
         return NULL;
@@ -1271,7 +1272,7 @@ more_input:
          * i_nal_size_length == 0, which is the case for codecs other
          * than H.264 */
         convert_h264_to_annexb( p_header->pBuffer, p_header->nFilledLen,
-                                p_sys->i_nal_size_length );
+                                p_sys->i_nal_size_length, &convert_state );
 #ifdef OMXIL_EXTRA_DEBUG
         msg_Dbg( p_dec, "EmptyThisBuffer %p, %p, %i", p_header, p_header->pBuffer,
                  (int)p_header->nFilledLen );