[vlc-devel] [RFC PATCH 1/7] move h264/hevc nal helper code to packetizer

Thomas Guillem thomas at gllm.fr
Thu Apr 23 19:30:49 CEST 2015


---
 modules/codec/Makefile.am                |  11 +-
 modules/codec/crystalhd.c                |   2 +-
 modules/codec/h264_nal.c                 | 169 -------------------------------
 modules/codec/h264_nal.h                 |  66 ------------
 modules/codec/hevc_nal.c                 | 107 -------------------
 modules/codec/hevc_nal.h                 |  38 -------
 modules/codec/mft.c                      |   2 +-
 modules/codec/omxil/android_mediacodec.c |   4 +-
 modules/codec/omxil/omxil.c              |   4 +-
 modules/codec/omxil/utils.c              |   2 +-
 modules/packetizer/Makefile.am           |   2 +-
 modules/packetizer/h264.c                |   2 +-
 modules/packetizer/h264_nal.c            | 169 +++++++++++++++++++++++++++++++
 modules/packetizer/h264_nal.h            |  66 ++++++++++++
 modules/packetizer/hevc_nal.c            | 107 +++++++++++++++++++
 modules/packetizer/hevc_nal.h            |  38 +++++++
 16 files changed, 395 insertions(+), 394 deletions(-)
 delete mode 100644 modules/codec/h264_nal.c
 delete mode 100644 modules/codec/h264_nal.h
 delete mode 100644 modules/codec/hevc_nal.c
 delete mode 100644 modules/codec/hevc_nal.h
 create mode 100644 modules/packetizer/h264_nal.c
 create mode 100644 modules/packetizer/h264_nal.h
 create mode 100644 modules/packetizer/hevc_nal.c
 create mode 100644 modules/packetizer/hevc_nal.h

diff --git a/modules/codec/Makefile.am b/modules/codec/Makefile.am
index 9c31230..cea527b 100644
--- a/modules/codec/Makefile.am
+++ b/modules/codec/Makefile.am
@@ -375,8 +375,8 @@ noinst_HEADERS += \
 
 libomxil_plugin_la_SOURCES = \
 	codec/omxil/utils.c codec/omxil/omxil_utils.h \
-	codec/h264_nal.c codec/h264_nal.h \
-	codec/hevc_nal.c codec/hevc_nal.h \
+	packetizer/h264_nal.c packetizer/h264_nal.h \
+	packetizer/hevc_nal.c packetizer/hevc_nal.h \
 	codec/omxil/qcom.c codec/omxil/qcom.h \
 	codec/omxil/omxil.c codec/omxil/omxil.h codec/omxil/omxil_core.c codec/omxil/omxil_core.h \
 	video_chroma/copy.c
@@ -396,7 +396,8 @@ libiomx_plugin_la_LIBADD = $(libomxil_plugin_la_LIBADD)
 libmediacodec_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/codec/omxil
 libmediacodec_plugin_la_SOURCES = codec/omxil/android_mediacodec.c codec/omxil/utils.c \
 	video_chroma/copy.c codec/omxil/android_opaque.c codec/omxil/android_opaque.h \
-	codec/h264_nal.c codec/h264_nal.h codec/hevc_nal.c codec/hevc_nal.h
+	packetizer/h264_nal.c packetizer/h264_nal.h
+	packetizer/hevc_nal.c packetizer/hevc_nal.h
 
 codec_LTLIBRARIES += $(LTLIBomxil) $(LTLIBomxil_vout)
 EXTRA_LTLIBRARIES += libomxil_plugin.la libomxil_vout_plugin.la
@@ -474,7 +475,7 @@ codec_LTLIBRARIES += $(LTLIBtwolame)
 
 ### Hardware encoders ###
 
-libcrystalhd_plugin_la_SOURCES = codec/crystalhd.c codec/h264_nal.c codec/h264_nal.h
+libcrystalhd_plugin_la_SOURCES = codec/crystalhd.c packetizer/h264_nal.c packetizer/h264_nal.h
 libcrystalhd_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(codecdir)'
 libcrystalhd_plugin_la_LIBADD = $(LIBS_crystalhd)
 EXTRA_LTLIBRARIES += libcrystalhd_plugin.la
@@ -498,7 +499,7 @@ libdmo_plugin_la_LIBADD += -lole32 -luuid
 codec_LTLIBRARIES += libdmo_plugin.la
 endif
 
-libmft_plugin_la_SOURCES = codec/mft.c codec/h264_nal.c codec/h264_nal.h
+libmft_plugin_la_SOURCES = codec/mft.c packetizer/h264_nal.c packetizer/h264_nal.h
 if HAVE_WIN32
 libmft_plugin_la_LIBADD = -lole32 -luuid -lmfuuid -lmfplat
 codec_LTLIBRARIES += libmft_plugin.la
diff --git a/modules/codec/crystalhd.c b/modules/codec/crystalhd.c
index b8e39af..d3b99ba 100644
--- a/modules/codec/crystalhd.c
+++ b/modules/codec/crystalhd.c
@@ -39,7 +39,7 @@
 #include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_codec.h>
-#include "h264_nal.h"
+#include "../packetizer/h264_nal.h"
 
 /* Workaround for some versions of libcrystalHD */
 #if !defined(_WIN32) && !defined(__APPLE__)
diff --git a/modules/codec/h264_nal.c b/modules/codec/h264_nal.c
deleted file mode 100644
index 2a375c2..0000000
--- a/modules/codec/h264_nal.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*****************************************************************************
- * Copyright © 2010-2014 VideoLAN
- *
- * Authors: Jean-Baptiste Kempf <jb at videolan.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-#include "h264_nal.h"
-
-#include <limits.h>
-
-int convert_sps_pps( decoder_t *p_dec, const uint8_t *p_buf,
-                     uint32_t i_buf_size, uint8_t *p_out_buf,
-                     uint32_t i_out_buf_size, uint32_t *p_sps_pps_size,
-                     uint32_t *p_nal_size)
-{
-    int i_profile;
-    uint32_t i_data_size = i_buf_size, i_nal_size, i_sps_pps_size = 0;
-    unsigned int i_loop_end;
-
-    /* */
-    if( i_data_size < 7 )
-    {
-        msg_Err( p_dec, "Input Metadata too small" );
-        return VLC_ENOMEM;
-    }
-
-    /* Read infos in first 6 bytes */
-    i_profile = (p_buf[1] << 16) | (p_buf[2] << 8) | p_buf[3];
-    if (p_nal_size)
-        *p_nal_size  = (p_buf[4] & 0x03) + 1;
-    p_buf       += 5;
-    i_data_size -= 5;
-
-    for ( unsigned int j = 0; j < 2; j++ )
-    {
-        /* First time is SPS, Second is PPS */
-        if( i_data_size < 1 )
-        {
-            msg_Err( p_dec, "PPS too small after processing SPS/PPS %u",
-                    i_data_size );
-            return VLC_ENOMEM;
-        }
-        i_loop_end = p_buf[0] & (j == 0 ? 0x1f : 0xff);
-        p_buf++; i_data_size--;
-
-        for ( unsigned int i = 0; i < i_loop_end; i++)
-        {
-            if( i_data_size < 2 )
-            {
-                msg_Err( p_dec, "SPS is too small %u", i_data_size );
-                return VLC_ENOMEM;
-            }
-
-            i_nal_size = (p_buf[0] << 8) | p_buf[1];
-            p_buf += 2;
-            i_data_size -= 2;
-
-            if( i_data_size < i_nal_size )
-            {
-                msg_Err( p_dec, "SPS size does not match NAL specified size %u",
-                        i_data_size );
-                return VLC_ENOMEM;
-            }
-            if( i_sps_pps_size + 4 + i_nal_size > i_out_buf_size )
-            {
-                msg_Err( p_dec, "Output SPS/PPS buffer too small" );
-                return VLC_ENOMEM;
-            }
-
-            p_out_buf[i_sps_pps_size++] = 0;
-            p_out_buf[i_sps_pps_size++] = 0;
-            p_out_buf[i_sps_pps_size++] = 0;
-            p_out_buf[i_sps_pps_size++] = 1;
-
-            memcpy( p_out_buf + i_sps_pps_size, p_buf, i_nal_size );
-            i_sps_pps_size += i_nal_size;
-
-            p_buf += i_nal_size;
-            i_data_size -= i_nal_size;
-        }
-    }
-
-    *p_sps_pps_size = i_sps_pps_size;
-
-    return VLC_SUCCESS;
-}
-
-void convert_h264_to_annexb( uint8_t *p_buf, uint32_t i_len,
-                             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 > 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;
-        }
-    }
-}
-
-bool h264_get_profile_level(const es_format_t *p_fmt, size_t *p_profile,
-                            size_t *p_level, size_t *p_nal_size)
-{
-    uint8_t *p = (uint8_t*)p_fmt->p_extra;
-    if(!p || !p_fmt->p_extra) return false;
-
-    /* Check the profile / level */
-    if (p_fmt->i_original_fourcc == VLC_FOURCC('a','v','c','1') && p[0] == 1)
-    {
-        if (p_fmt->i_extra < 12) return false;
-        if (p_nal_size) *p_nal_size = 1 + (p[4]&0x03);
-        if (!(p[5]&0x1f)) return false;
-        p += 8;
-    }
-    else
-    {
-        if (p_fmt->i_extra < 8) return false;
-        if (!p[0] && !p[1] && !p[2] && p[3] == 1) p += 4;
-        else if (!p[0] && !p[1] && p[2] == 1) p += 3;
-        else return false;
-    }
-
-    if ( ((*p++)&0x1f) != 7) return false;
-
-    /* Get profile/level out of first SPS */
-    if (p_profile) *p_profile = p[0];
-    if (p_level) *p_level = p[2];
-    return true;
-}
diff --git a/modules/codec/h264_nal.h b/modules/codec/h264_nal.h
deleted file mode 100644
index 7028fcf..0000000
--- a/modules/codec/h264_nal.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*****************************************************************************
- * Copyright © 2010-2014 VideoLAN
- *
- * Authors: Jean-Baptiste Kempf <jb at videolan.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-#ifndef H264_NAL_H
-# define H264_NAL_H
-
-# ifdef HAVE_CONFIG_H
-#  include "config.h"
-# endif
-
-# include <vlc_common.h>
-# include <vlc_codec.h>
-
-#define PROFILE_H264_BASELINE             66
-#define PROFILE_H264_MAIN                 77
-#define PROFILE_H264_EXTENDED             88
-#define PROFILE_H264_HIGH                 100
-#define PROFILE_H264_HIGH_10              110
-#define PROFILE_H264_HIGH_422             122
-#define PROFILE_H264_HIGH_444             144
-#define PROFILE_H264_HIGH_444_PREDICTIVE  244
-
-#define PROFILE_H264_CAVLC_INTRA          44
-#define PROFILE_H264_SVC_BASELINE         83
-#define PROFILE_H264_SVC_HIGH             86
-#define PROFILE_H264_MVC_STEREO_HIGH      128
-#define PROFILE_H264_MVC_MULTIVIEW_HIGH   118
-
-/* Parse the SPS/PPS Metadata and convert it to annex b format */
-int convert_sps_pps( decoder_t *p_dec, const uint8_t *p_buf,
-                     uint32_t i_buf_size, uint8_t *p_out_buf,
-                     uint32_t i_out_buf_size, uint32_t *p_sps_pps_size,
-                     uint32_t *p_nal_size);
-
-/* Convert H.264 NAL format to annex b in-place */
-struct H264ConvertState {
-    uint32_t nal_len;
-    uint32_t nal_pos;
-};
-
-void convert_h264_to_annexb( uint8_t *p_buf, uint32_t i_len,
-                             size_t i_nal_size,
-                             struct H264ConvertState *state );
-
-/* Get level and Profile */
-bool h264_get_profile_level(const es_format_t *p_fmt, size_t *p_profile,
-                            size_t *p_level, size_t *p_nal_size);
-
-#endif /* H264_NAL_H */
diff --git a/modules/codec/hevc_nal.c b/modules/codec/hevc_nal.c
deleted file mode 100644
index 45c5218..0000000
--- a/modules/codec/hevc_nal.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*****************************************************************************
- * Copyright © 2010-2014 VideoLAN
- *
- * Authors: Thomas Guillem <thomas.guillem at gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-#include "hevc_nal.h"
-
-#include <limits.h>
-
-/* Inspired by libavcodec/hevc.c */
-int convert_hevc_nal_units(decoder_t *p_dec, const uint8_t *p_buf,
-                           uint32_t i_buf_size, uint8_t *p_out_buf,
-                           uint32_t i_out_buf_size, uint32_t *p_sps_pps_size,
-                           uint32_t *p_nal_size)
-{
-    int i, num_arrays;
-    const uint8_t *p_end = p_buf + i_buf_size;
-    uint32_t i_sps_pps_size = 0;
-
-    if( i_buf_size <= 3 || ( !p_buf[0] && !p_buf[1] && p_buf[2] <= 1 ) )
-        return VLC_EGENERIC;
-
-    if( p_end - p_buf < 23 )
-    {
-        msg_Err( p_dec, "Input Metadata too small" );
-        return VLC_ENOMEM;
-    }
-
-    p_buf += 21;
-
-    if( p_nal_size )
-        *p_nal_size = (*p_buf & 0x03) + 1;
-    p_buf++;
-
-    num_arrays = *p_buf++;
-
-    for( i = 0; i < num_arrays; i++ )
-    {
-        int type, cnt, j;
-
-        if( p_end - p_buf < 3 )
-        {
-            msg_Err( p_dec, "Input Metadata too small" );
-            return VLC_ENOMEM;
-        }
-        type = *(p_buf++) & 0x3f;
-        VLC_UNUSED(type);
-
-        cnt = p_buf[0] << 8 | p_buf[1];
-        p_buf += 2;
-
-        for( j = 0; j < cnt; j++ )
-        {
-            int i_nal_size;
-
-            if( p_end - p_buf < 2 )
-            {
-                msg_Err( p_dec, "Input Metadata too small" );
-                return VLC_ENOMEM;
-            }
-            
-            i_nal_size = p_buf[0] << 8 | p_buf[1];
-            p_buf += 2;
-
-            if( i_nal_size < 0 || p_end - p_buf < i_nal_size )
-            {
-                msg_Err( p_dec, "NAL unit size does not match Input Metadata size" );
-                return VLC_ENOMEM;
-            }
-
-            if( i_sps_pps_size + 4 + i_nal_size > i_out_buf_size )
-            {
-                msg_Err( p_dec, "Output buffer too small" );
-                return VLC_ENOMEM;
-            }
-
-            p_out_buf[i_sps_pps_size++] = 0;
-            p_out_buf[i_sps_pps_size++] = 0;
-            p_out_buf[i_sps_pps_size++] = 0;
-            p_out_buf[i_sps_pps_size++] = 1;
-
-            memcpy(p_out_buf + i_sps_pps_size, p_buf, i_nal_size);
-            p_buf += i_nal_size;
-
-            i_sps_pps_size += i_nal_size;
-        }
-    }
-
-    *p_sps_pps_size = i_sps_pps_size;
-
-    return VLC_SUCCESS;
-}
diff --git a/modules/codec/hevc_nal.h b/modules/codec/hevc_nal.h
deleted file mode 100644
index 17625e9..0000000
--- a/modules/codec/hevc_nal.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*****************************************************************************
- * Copyright © 2010-2014 VideoLAN
- *
- * Authors: Thomas Guillem <thomas.guillem at gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-#ifndef HEVC_NAL_H
-# define HEVC_NAL_H
-
-# ifdef HAVE_CONFIG_H
-#  include "config.h"
-# endif
-
-# include <vlc_common.h>
-# include <vlc_codec.h>
-
-/* Parse the hvcC Metadata and convert it to annex b format */
-int convert_hevc_nal_units( decoder_t *p_dec, const uint8_t *p_buf,
-                            uint32_t i_buf_size, uint8_t *p_out_buf,
-                            uint32_t i_out_buf_size, uint32_t *p_sps_pps_size,
-                            uint32_t *p_nal_size);
-
-
-#endif /* HEVC_NAL_H */
diff --git a/modules/codec/mft.c b/modules/codec/mft.c
index 22e647f..8c9373a 100644
--- a/modules/codec/mft.c
+++ b/modules/codec/mft.c
@@ -42,7 +42,7 @@
 #include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_codec.h>
-#include <h264_nal.h>
+#include "../packetizer/h264_nal.h"
 #define _VIDEOINFOHEADER_
 #include <vlc_codecs.h>
 
diff --git a/modules/codec/omxil/android_mediacodec.c b/modules/codec/omxil/android_mediacodec.c
index 5474acf..7856de9 100644
--- a/modules/codec/omxil/android_mediacodec.c
+++ b/modules/codec/omxil/android_mediacodec.c
@@ -37,8 +37,8 @@
 #include <vlc_block_helper.h>
 #include <vlc_cpu.h>
 
-#include "../h264_nal.h"
-#include "../hevc_nal.h"
+#include "../../packetizer/h264_nal.h"
+#include "../../packetizer/hevc_nal.h"
 #include <OMX_Core.h>
 #include <OMX_Component.h>
 #include "omxil_utils.h"
diff --git a/modules/codec/omxil/omxil.c b/modules/codec/omxil/omxil.c
index 0176707..1418340 100644
--- a/modules/codec/omxil/omxil.c
+++ b/modules/codec/omxil/omxil.c
@@ -35,8 +35,8 @@
 #include <vlc_codec.h>
 #include <vlc_block_helper.h>
 #include <vlc_cpu.h>
-#include "../h264_nal.h"
-#include "../hevc_nal.h"
+#include "../../packetizer/h264_nal.h"
+#include "../../packetizer/hevc_nal.h"
 
 #include "omxil.h"
 #include "omxil_core.h"
diff --git a/modules/codec/omxil/utils.c b/modules/codec/omxil/utils.c
index 31a491d..9d01ee1 100644
--- a/modules/codec/omxil/utils.c
+++ b/modules/codec/omxil/utils.c
@@ -37,7 +37,7 @@
 #include "omxil.h"
 #include "qcom.h"
 #include "../../video_chroma/copy.h"
-#include "../h264_nal.h"
+#include "../../packetizer/h264_nal.h"
 
 /*****************************************************************************
  * Events utility functions
diff --git a/modules/packetizer/Makefile.am b/modules/packetizer/Makefile.am
index 40ad488..b6bf074 100644
--- a/modules/packetizer/Makefile.am
+++ b/modules/packetizer/Makefile.am
@@ -5,7 +5,7 @@ libpacketizer_mpegvideo_plugin_la_SOURCES = packetizer/mpegvideo.c
 libpacketizer_mpeg4video_plugin_la_SOURCES = packetizer/mpeg4video.c
 libpacketizer_mpeg4audio_plugin_la_SOURCES = packetizer/mpeg4audio.c
 libpacketizer_h264_plugin_la_SOURCES = \
-	codec/h264_nal.c codec/h264_nal.h \
+	packetizer/h264_nal.c packetizer/h264_nal.h \
 	packetizer/h264.c
 libpacketizer_vc1_plugin_la_SOURCES = packetizer/vc1.c
 libpacketizer_mlp_plugin_la_SOURCES = packetizer/mlp.c
diff --git a/modules/packetizer/h264.c b/modules/packetizer/h264.c
index d89748f..d260901 100644
--- a/modules/packetizer/h264.c
+++ b/modules/packetizer/h264.c
@@ -41,7 +41,7 @@
 #include <vlc_block_helper.h>
 #include <vlc_bits.h>
 #include "../codec/cc.h"
-#include "../codec/h264_nal.h"
+#include "h264_nal.h"
 #include "packetizer_helper.h"
 #include "../demux/mpeg/mpeg_parser_helpers.h"
 
diff --git a/modules/packetizer/h264_nal.c b/modules/packetizer/h264_nal.c
new file mode 100644
index 0000000..2a375c2
--- /dev/null
+++ b/modules/packetizer/h264_nal.c
@@ -0,0 +1,169 @@
+/*****************************************************************************
+ * Copyright © 2010-2014 VideoLAN
+ *
+ * Authors: Jean-Baptiste Kempf <jb at videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include "h264_nal.h"
+
+#include <limits.h>
+
+int convert_sps_pps( decoder_t *p_dec, const uint8_t *p_buf,
+                     uint32_t i_buf_size, uint8_t *p_out_buf,
+                     uint32_t i_out_buf_size, uint32_t *p_sps_pps_size,
+                     uint32_t *p_nal_size)
+{
+    int i_profile;
+    uint32_t i_data_size = i_buf_size, i_nal_size, i_sps_pps_size = 0;
+    unsigned int i_loop_end;
+
+    /* */
+    if( i_data_size < 7 )
+    {
+        msg_Err( p_dec, "Input Metadata too small" );
+        return VLC_ENOMEM;
+    }
+
+    /* Read infos in first 6 bytes */
+    i_profile = (p_buf[1] << 16) | (p_buf[2] << 8) | p_buf[3];
+    if (p_nal_size)
+        *p_nal_size  = (p_buf[4] & 0x03) + 1;
+    p_buf       += 5;
+    i_data_size -= 5;
+
+    for ( unsigned int j = 0; j < 2; j++ )
+    {
+        /* First time is SPS, Second is PPS */
+        if( i_data_size < 1 )
+        {
+            msg_Err( p_dec, "PPS too small after processing SPS/PPS %u",
+                    i_data_size );
+            return VLC_ENOMEM;
+        }
+        i_loop_end = p_buf[0] & (j == 0 ? 0x1f : 0xff);
+        p_buf++; i_data_size--;
+
+        for ( unsigned int i = 0; i < i_loop_end; i++)
+        {
+            if( i_data_size < 2 )
+            {
+                msg_Err( p_dec, "SPS is too small %u", i_data_size );
+                return VLC_ENOMEM;
+            }
+
+            i_nal_size = (p_buf[0] << 8) | p_buf[1];
+            p_buf += 2;
+            i_data_size -= 2;
+
+            if( i_data_size < i_nal_size )
+            {
+                msg_Err( p_dec, "SPS size does not match NAL specified size %u",
+                        i_data_size );
+                return VLC_ENOMEM;
+            }
+            if( i_sps_pps_size + 4 + i_nal_size > i_out_buf_size )
+            {
+                msg_Err( p_dec, "Output SPS/PPS buffer too small" );
+                return VLC_ENOMEM;
+            }
+
+            p_out_buf[i_sps_pps_size++] = 0;
+            p_out_buf[i_sps_pps_size++] = 0;
+            p_out_buf[i_sps_pps_size++] = 0;
+            p_out_buf[i_sps_pps_size++] = 1;
+
+            memcpy( p_out_buf + i_sps_pps_size, p_buf, i_nal_size );
+            i_sps_pps_size += i_nal_size;
+
+            p_buf += i_nal_size;
+            i_data_size -= i_nal_size;
+        }
+    }
+
+    *p_sps_pps_size = i_sps_pps_size;
+
+    return VLC_SUCCESS;
+}
+
+void convert_h264_to_annexb( uint8_t *p_buf, uint32_t i_len,
+                             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 > 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;
+        }
+    }
+}
+
+bool h264_get_profile_level(const es_format_t *p_fmt, size_t *p_profile,
+                            size_t *p_level, size_t *p_nal_size)
+{
+    uint8_t *p = (uint8_t*)p_fmt->p_extra;
+    if(!p || !p_fmt->p_extra) return false;
+
+    /* Check the profile / level */
+    if (p_fmt->i_original_fourcc == VLC_FOURCC('a','v','c','1') && p[0] == 1)
+    {
+        if (p_fmt->i_extra < 12) return false;
+        if (p_nal_size) *p_nal_size = 1 + (p[4]&0x03);
+        if (!(p[5]&0x1f)) return false;
+        p += 8;
+    }
+    else
+    {
+        if (p_fmt->i_extra < 8) return false;
+        if (!p[0] && !p[1] && !p[2] && p[3] == 1) p += 4;
+        else if (!p[0] && !p[1] && p[2] == 1) p += 3;
+        else return false;
+    }
+
+    if ( ((*p++)&0x1f) != 7) return false;
+
+    /* Get profile/level out of first SPS */
+    if (p_profile) *p_profile = p[0];
+    if (p_level) *p_level = p[2];
+    return true;
+}
diff --git a/modules/packetizer/h264_nal.h b/modules/packetizer/h264_nal.h
new file mode 100644
index 0000000..7028fcf
--- /dev/null
+++ b/modules/packetizer/h264_nal.h
@@ -0,0 +1,66 @@
+/*****************************************************************************
+ * Copyright © 2010-2014 VideoLAN
+ *
+ * Authors: Jean-Baptiste Kempf <jb at videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef H264_NAL_H
+# define H264_NAL_H
+
+# ifdef HAVE_CONFIG_H
+#  include "config.h"
+# endif
+
+# include <vlc_common.h>
+# include <vlc_codec.h>
+
+#define PROFILE_H264_BASELINE             66
+#define PROFILE_H264_MAIN                 77
+#define PROFILE_H264_EXTENDED             88
+#define PROFILE_H264_HIGH                 100
+#define PROFILE_H264_HIGH_10              110
+#define PROFILE_H264_HIGH_422             122
+#define PROFILE_H264_HIGH_444             144
+#define PROFILE_H264_HIGH_444_PREDICTIVE  244
+
+#define PROFILE_H264_CAVLC_INTRA          44
+#define PROFILE_H264_SVC_BASELINE         83
+#define PROFILE_H264_SVC_HIGH             86
+#define PROFILE_H264_MVC_STEREO_HIGH      128
+#define PROFILE_H264_MVC_MULTIVIEW_HIGH   118
+
+/* Parse the SPS/PPS Metadata and convert it to annex b format */
+int convert_sps_pps( decoder_t *p_dec, const uint8_t *p_buf,
+                     uint32_t i_buf_size, uint8_t *p_out_buf,
+                     uint32_t i_out_buf_size, uint32_t *p_sps_pps_size,
+                     uint32_t *p_nal_size);
+
+/* Convert H.264 NAL format to annex b in-place */
+struct H264ConvertState {
+    uint32_t nal_len;
+    uint32_t nal_pos;
+};
+
+void convert_h264_to_annexb( uint8_t *p_buf, uint32_t i_len,
+                             size_t i_nal_size,
+                             struct H264ConvertState *state );
+
+/* Get level and Profile */
+bool h264_get_profile_level(const es_format_t *p_fmt, size_t *p_profile,
+                            size_t *p_level, size_t *p_nal_size);
+
+#endif /* H264_NAL_H */
diff --git a/modules/packetizer/hevc_nal.c b/modules/packetizer/hevc_nal.c
new file mode 100644
index 0000000..45c5218
--- /dev/null
+++ b/modules/packetizer/hevc_nal.c
@@ -0,0 +1,107 @@
+/*****************************************************************************
+ * Copyright © 2010-2014 VideoLAN
+ *
+ * Authors: Thomas Guillem <thomas.guillem at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include "hevc_nal.h"
+
+#include <limits.h>
+
+/* Inspired by libavcodec/hevc.c */
+int convert_hevc_nal_units(decoder_t *p_dec, const uint8_t *p_buf,
+                           uint32_t i_buf_size, uint8_t *p_out_buf,
+                           uint32_t i_out_buf_size, uint32_t *p_sps_pps_size,
+                           uint32_t *p_nal_size)
+{
+    int i, num_arrays;
+    const uint8_t *p_end = p_buf + i_buf_size;
+    uint32_t i_sps_pps_size = 0;
+
+    if( i_buf_size <= 3 || ( !p_buf[0] && !p_buf[1] && p_buf[2] <= 1 ) )
+        return VLC_EGENERIC;
+
+    if( p_end - p_buf < 23 )
+    {
+        msg_Err( p_dec, "Input Metadata too small" );
+        return VLC_ENOMEM;
+    }
+
+    p_buf += 21;
+
+    if( p_nal_size )
+        *p_nal_size = (*p_buf & 0x03) + 1;
+    p_buf++;
+
+    num_arrays = *p_buf++;
+
+    for( i = 0; i < num_arrays; i++ )
+    {
+        int type, cnt, j;
+
+        if( p_end - p_buf < 3 )
+        {
+            msg_Err( p_dec, "Input Metadata too small" );
+            return VLC_ENOMEM;
+        }
+        type = *(p_buf++) & 0x3f;
+        VLC_UNUSED(type);
+
+        cnt = p_buf[0] << 8 | p_buf[1];
+        p_buf += 2;
+
+        for( j = 0; j < cnt; j++ )
+        {
+            int i_nal_size;
+
+            if( p_end - p_buf < 2 )
+            {
+                msg_Err( p_dec, "Input Metadata too small" );
+                return VLC_ENOMEM;
+            }
+            
+            i_nal_size = p_buf[0] << 8 | p_buf[1];
+            p_buf += 2;
+
+            if( i_nal_size < 0 || p_end - p_buf < i_nal_size )
+            {
+                msg_Err( p_dec, "NAL unit size does not match Input Metadata size" );
+                return VLC_ENOMEM;
+            }
+
+            if( i_sps_pps_size + 4 + i_nal_size > i_out_buf_size )
+            {
+                msg_Err( p_dec, "Output buffer too small" );
+                return VLC_ENOMEM;
+            }
+
+            p_out_buf[i_sps_pps_size++] = 0;
+            p_out_buf[i_sps_pps_size++] = 0;
+            p_out_buf[i_sps_pps_size++] = 0;
+            p_out_buf[i_sps_pps_size++] = 1;
+
+            memcpy(p_out_buf + i_sps_pps_size, p_buf, i_nal_size);
+            p_buf += i_nal_size;
+
+            i_sps_pps_size += i_nal_size;
+        }
+    }
+
+    *p_sps_pps_size = i_sps_pps_size;
+
+    return VLC_SUCCESS;
+}
diff --git a/modules/packetizer/hevc_nal.h b/modules/packetizer/hevc_nal.h
new file mode 100644
index 0000000..17625e9
--- /dev/null
+++ b/modules/packetizer/hevc_nal.h
@@ -0,0 +1,38 @@
+/*****************************************************************************
+ * Copyright © 2010-2014 VideoLAN
+ *
+ * Authors: Thomas Guillem <thomas.guillem at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef HEVC_NAL_H
+# define HEVC_NAL_H
+
+# ifdef HAVE_CONFIG_H
+#  include "config.h"
+# endif
+
+# include <vlc_common.h>
+# include <vlc_codec.h>
+
+/* Parse the hvcC Metadata and convert it to annex b format */
+int convert_hevc_nal_units( decoder_t *p_dec, const uint8_t *p_buf,
+                            uint32_t i_buf_size, uint8_t *p_out_buf,
+                            uint32_t i_out_buf_size, uint32_t *p_sps_pps_size,
+                            uint32_t *p_nal_size);
+
+
+#endif /* HEVC_NAL_H */
-- 
2.1.3




More information about the vlc-devel mailing list