[vlc-commits] packetizer: hevc: extract closed captions

Francois Cartegnie git at videolan.org
Fri Oct 7 16:33:30 CEST 2016


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri Oct  7 14:55:39 2016 +0200| [18ae72bbc4f1f26bbecc235fe3c1e56f78b3a2c2] | committer: Francois Cartegnie

packetizer: hevc: extract closed captions

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=18ae72bbc4f1f26bbecc235fe3c1e56f78b3a2c2
---

 modules/packetizer/Makefile.am   |  1 +
 modules/packetizer/hevc.c        | 59 ++++++++++++++++++++++++++++--
 modules/packetizer/hxxx_common.c | 77 ++++++++++++++++++++++++++++++++++++++++
 modules/packetizer/hxxx_common.h | 15 ++++++++
 4 files changed, 150 insertions(+), 2 deletions(-)

diff --git a/modules/packetizer/Makefile.am b/modules/packetizer/Makefile.am
index 7ccf4a5..3801b36 100644
--- a/modules/packetizer/Makefile.am
+++ b/modules/packetizer/Makefile.am
@@ -16,6 +16,7 @@ libpacketizer_dirac_plugin_la_SOURCES = packetizer/dirac.c
 libpacketizer_flac_plugin_la_SOURCES = packetizer/flac.c
 libpacketizer_hevc_plugin_la_SOURCES = packetizer/hevc.c \
 	packetizer/hevc_nal.h packetizer/hevc_nal.c \
+	packetizer/hxxx_sei.c packetizer/hxxx_sei.h \
 	packetizer/hxxx_nal.h \
 	packetizer/hxxx_common.c packetizer/hxxx_common.h
 libpacketizer_a52_plugin_la_SOURCES = packetizer/a52.c packetizer/a52.h
diff --git a/modules/packetizer/hevc.c b/modules/packetizer/hevc.c
index 15ca6bc..e590f3a 100644
--- a/modules/packetizer/hevc.c
+++ b/modules/packetizer/hevc.c
@@ -33,12 +33,14 @@
 #include <vlc_plugin.h>
 #include <vlc_codec.h>
 #include <vlc_block.h>
+#include <vlc_bits.h>
 
 #include <vlc_block_helper.h>
 #include "packetizer_helper.h"
 #include "startcode_helper.h"
 #include "hevc_nal.h"
 #include "hxxx_nal.h"
+#include "hxxx_sei.h"
 #include "hxxx_common.h"
 
 /*****************************************************************************
@@ -66,6 +68,8 @@ static void PacketizeReset(void *p_private, bool b_broken);
 static block_t *PacketizeParse(void *p_private, bool *pb_ts_used, block_t *);
 static block_t *ParseNALBlock(decoder_t *, bool *pb_ts_used, block_t *);
 static int PacketizeValidate(void *p_private, block_t *);
+static bool ParseSEICallback( const hxxx_sei_data_t *, void * );
+static block_t *GetCc( decoder_t *, bool pb_present[4] );
 
 struct decoder_sys_t
 {
@@ -83,6 +87,9 @@ struct decoder_sys_t
     hevc_sequence_parameter_set_t *rgi_p_decsps[HEVC_SPS_MAX];
     hevc_picture_parameter_set_t  *rgi_p_decpps[HEVC_PPS_MAX];
     bool b_init_sequence_complete;
+
+    /* */
+    cc_storage_t *p_ccs;
 };
 
 static const uint8_t p_hevc_startcode[3] = {0x00, 0x00, 0x01};
@@ -154,6 +161,13 @@ static int Open(vlc_object_t *p_this)
     if (!p_dec->p_sys)
         return VLC_ENOMEM;
 
+    p_sys->p_ccs = cc_storage_new();
+    if(unlikely(!p_sys->p_ccs))
+    {
+        free(p_dec->p_sys);
+        return VLC_ENOMEM;
+    }
+
     INITQ(pre);
     INITQ(frame);
     INITQ(post);
@@ -191,6 +205,7 @@ static int Open(vlc_object_t *p_this)
         p_dec->pf_packetize = PacketizeAnnexB;
     }
     p_dec->pf_flush = PacketizeFlush;
+    p_dec->pf_get_cc = GetCc;
 
     if(p_dec->fmt_out.i_extra)
     {
@@ -233,6 +248,8 @@ static void Close(vlc_object_t *p_this)
             hevc_rbsp_release_vps(p_sys->rgi_p_decvps[i]);
     }
 
+    cc_storage_delete( p_sys->p_ccs );
+
     free(p_sys);
 }
 
@@ -261,6 +278,14 @@ static void PacketizeFlush( decoder_t *p_dec )
     packetizer_Flush( &p_sys->packetizer );
 }
 
+/*****************************************************************************
+ * GetCc:
+ *****************************************************************************/
+static block_t *GetCc( decoder_t *p_dec, bool pb_present[4] )
+{
+    return cc_storage_get_current( p_dec->p_sys->p_ccs, pb_present );
+}
+
 /****************************************************************************
  * Packetizer Helpers
  ****************************************************************************/
@@ -440,6 +465,9 @@ static block_t *ParseVCL(decoder_t *p_dec, uint8_t i_nal_type, block_t *p_frag)
         p_sys->b_init_sequence_complete = true;
     }
 
+    if( !p_sys->b_init_sequence_complete )
+        cc_storage_reset( p_sys->p_ccs );
+
     block_ChainLastAppend(&p_sys->frame.pp_chain_last, p_frag);
 
     return p_outputchain;
@@ -511,8 +539,14 @@ static block_t * ParseAUHead(decoder_t *p_dec, uint8_t i_nal_type, block_t *p_na
                     }
                 }
             }
+            break;
         }
-        // ft
+
+        case HEVC_NAL_PREF_SEI:
+            HxxxParse_AnnexB_SEI( p_nalb->p_buffer, p_nalb->i_buffer,
+                                  2 /* nal header */, ParseSEICallback, p_dec );
+            break;
+
         default:
             break;
     }
@@ -535,6 +569,11 @@ static block_t * ParseAUTail(decoder_t *p_dec, uint8_t i_nal_type, block_t *p_na
         case HEVC_NAL_EOB:
             p_ret = OutputQueues(p_sys, true);
             break;
+
+        case HEVC_NAL_SUFF_SEI:
+            HxxxParse_AnnexB_SEI( p_nalb->p_buffer, p_nalb->i_buffer,
+                                  2 /* nal header */, ParseSEICallback, p_dec );
+            break;
     }
 
     if(!p_ret && p_sys->frame.p_chain == NULL)
@@ -630,12 +669,17 @@ static block_t *ParseNALBlock(decoder_t *p_dec, bool *pb_ts_used, block_t *p_fra
 static block_t *PacketizeParse(void *p_private, bool *pb_ts_used, block_t *p_block)
 {
     decoder_t *p_dec = p_private;
+    decoder_sys_t *p_sys = p_dec->p_sys;
 
     /* Remove trailing 0 bytes */
     while (p_block->i_buffer > 5 && p_block->p_buffer[p_block->i_buffer-1] == 0x00 )
         p_block->i_buffer--;
 
-    return ParseNALBlock( p_dec, pb_ts_used, p_block );
+    p_block = ParseNALBlock( p_dec, pb_ts_used, p_block );
+    if( p_block )
+        cc_storage_commit( p_sys->p_ccs, p_block );
+
+    return p_block;
 }
 
 static int PacketizeValidate( void *p_private, block_t *p_au )
@@ -644,3 +688,14 @@ static int PacketizeValidate( void *p_private, block_t *p_au )
     VLC_UNUSED(p_au);
     return VLC_SUCCESS;
 }
+
+static bool ParseSEICallback( const hxxx_sei_data_t *p_sei_data, void *cbdata )
+{
+    decoder_t *p_dec = (decoder_t *) cbdata;
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    if( p_sei_data->i_type == HXXX_SEI_USER_DATA_REGISTERED_ITU_T_T35 )
+        cc_storage_append( p_sys->p_ccs, true, p_sei_data->itu_t35.p_cc, p_sei_data->itu_t35.i_cc );
+
+    return true;
+}
diff --git a/modules/packetizer/hxxx_common.c b/modules/packetizer/hxxx_common.c
index 5c35c43..137330e 100644
--- a/modules/packetizer/hxxx_common.c
+++ b/modules/packetizer/hxxx_common.c
@@ -25,6 +25,83 @@
 
 #include <vlc_block.h>
 #include <vlc_codec.h>
+#include "../codec/cc.h"
+
+/****************************************************************************
+ * Closed captions handling
+ ****************************************************************************/
+struct cc_storage_t
+{
+    uint32_t i_flags;
+    mtime_t i_dts;
+    mtime_t i_pts;
+    cc_data_t current;
+    cc_data_t next;
+};
+
+cc_storage_t * cc_storage_new( void )
+{
+    cc_storage_t *p_ccs = malloc( sizeof(*p_ccs) );
+    if( likely(p_ccs) )
+    {
+        p_ccs->i_pts = VLC_TS_INVALID;
+        p_ccs->i_dts = VLC_TS_INVALID;
+        p_ccs->i_flags = 0;
+        cc_Init( &p_ccs->current );
+        cc_Init( &p_ccs->next );
+    }
+    return p_ccs;
+}
+
+void cc_storage_delete( cc_storage_t *p_ccs )
+{
+    cc_Exit( &p_ccs->current );
+    cc_Exit( &p_ccs->next );
+    free( p_ccs );
+}
+
+void cc_storage_reset( cc_storage_t *p_ccs )
+{
+    cc_Flush( &p_ccs->next );
+}
+
+void cc_storage_append( cc_storage_t *p_ccs, bool b_top_field_first,
+                                      const uint8_t *p_buf, size_t i_buf )
+{
+    cc_Extract( &p_ccs->next, b_top_field_first, p_buf, i_buf );
+}
+
+void cc_storage_commit( cc_storage_t *p_ccs, block_t *p_pic )
+{
+    p_ccs->i_pts = p_pic->i_pts;
+    p_ccs->i_dts = p_pic->i_dts;
+    p_ccs->i_flags = p_pic->i_flags;
+    p_ccs->current = p_ccs->next;
+    cc_Flush( &p_ccs->next );
+}
+
+block_t * cc_storage_get_current( cc_storage_t *p_ccs, bool pb_present[4] )
+{
+    block_t *p_block;
+
+    for( int i = 0; i < 4; i++ )
+        pb_present[i] = p_ccs->current.pb_present[i];
+
+    if( p_ccs->current.i_data <= 0 )
+        return NULL;
+
+    p_block = block_Alloc( p_ccs->current.i_data);
+    if( p_block )
+    {
+        memcpy( p_block->p_buffer, p_ccs->current.p_data, p_ccs->current.i_data );
+        p_block->i_dts =
+        p_block->i_pts = p_ccs->current.b_reorder ? p_ccs->i_pts : p_ccs->i_dts;
+        p_block->i_flags = ( p_ccs->current.b_reorder  ? p_ccs->i_flags : BLOCK_FLAG_TYPE_P ) & BLOCK_FLAG_TYPE_MASK;
+    }
+    cc_Flush( &p_ccs->current );
+
+    return p_block;
+}
 
 /****************************************************************************
  * PacketizeXXC1: Takes VCL blocks of data and creates annexe B type NAL stream
diff --git a/modules/packetizer/hxxx_common.h b/modules/packetizer/hxxx_common.h
index 3e5830e..89d20e7 100644
--- a/modules/packetizer/hxxx_common.h
+++ b/modules/packetizer/hxxx_common.h
@@ -22,6 +22,21 @@
 
 #include <vlc_common.h>
 
+/* */
+typedef struct cc_storage_t cc_storage_t;
+
+cc_storage_t * cc_storage_new( void );
+void cc_storage_delete( cc_storage_t *p_ccs );
+
+void cc_storage_reset( cc_storage_t *p_ccs );
+void cc_storage_append( cc_storage_t *p_ccs, bool b_top_field_first,
+                                      const uint8_t *p_buf, size_t i_buf );
+void cc_storage_commit( cc_storage_t *p_ccs, block_t *p_pic );
+
+block_t * cc_storage_get_current( cc_storage_t *p_ccs, bool pb_present[4] );
+
+/* */
+
 typedef block_t * (*pf_annexb_nal_packetizer)(decoder_t *, bool *, block_t *);
 block_t *PacketizeXXC1( decoder_t *, uint8_t, block_t **, pf_annexb_nal_packetizer );
 



More information about the vlc-commits mailing list