[vlc-devel] [PATCH] Allow hevc muxing in mp4

Rafaël Carré funman at videolan.org
Mon Feb 24 10:01:19 CET 2014


Hello,

On 02/22/14 17:47, Denis Charmet wrote:
> ---
>  modules/demux/Makefile.am                |   2 +-
>  modules/demux/mpeg/hevc.c                |  68 +-------
>  modules/demux/mpeg/mpeg_parser_helpers.h |  81 ++++++++++
>  modules/mux/Modules.am                   |   2 +-
>  modules/mux/mp4.c                        | 268 ++++++++++++++++++++++++++++++-
>  modules/packetizer/hevc.c                |   4 +-
>  6 files changed, 357 insertions(+), 68 deletions(-)
>  create mode 100644 modules/demux/mpeg/mpeg_parser_helpers.h
> 
> diff --git a/modules/demux/Makefile.am b/modules/demux/Makefile.am
> index 0cab9eb..3cfb523 100644
> --- a/modules/demux/Makefile.am
> +++ b/modules/demux/Makefile.am
> @@ -162,7 +162,7 @@ demux_LTLIBRARIES += libes_plugin.la
>  libh264_plugin_la_SOURCES = demux/mpeg/h264.c
>  demux_LTLIBRARIES += libh264_plugin.la
>  
> -libhevc_plugin_la_SOURCES = demux/mpeg/hevc.c
> +libhevc_plugin_la_SOURCES = demux/mpeg/hevc.c demux/mpeg/mpeg_parser_helpers.h
>  demux_LTLIBRARIES += libhevc_plugin.la
>  
>  libmkv_plugin_la_SOURCES = \
> diff --git a/modules/demux/mpeg/hevc.c b/modules/demux/mpeg/hevc.c
> index 39f9408..8021e17 100644
> --- a/modules/demux/mpeg/hevc.c
> +++ b/modules/demux/mpeg/hevc.c
> @@ -35,6 +35,7 @@
>  #include <vlc_codec.h>
>  #include <vlc_bits.h>
>  
> +#include "mpeg_parser_helpers.h"
>  
>  /*****************************************************************************
>   * Module descriptor
> @@ -185,7 +186,7 @@ static int Demux( demux_t *p_demux)
>              p_block_out->i_pts = VLC_TS_INVALID;
>  
>              /*Get fps from vps if available and not already forced*/
> -            if( p_sys->f_fps == 0.0f && ( p_block_out->p_buffer[3] & 0x7E ) == 0x40 )
> +            if( p_sys->f_fps == 0.0f && ( p_block_out->p_buffer[4] & 0x7E ) == 0x40 )

No need to check if block is large enough here? (i_buffer >= 5)

>              {
>                  if( getFPS( p_demux, p_block_out) )
>                  {
> @@ -195,9 +196,9 @@ static int Demux( demux_t *p_demux)
>              }
>  
>              /* Update DTS only on VCL NAL*/
> -            if( ( p_block_out->p_buffer[3]&0x7E ) < 0x40 && p_sys->f_fps )
> +            if( ( p_block_out->p_buffer[4]&0x7E ) < 0x40 && p_sys->f_fps )

Maybe p_buffer[4] & 0x7e should be cached.

>              {
> -                es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_dts );
> +                es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + p_sys->i_dts );

Initialize i_dts to VLC_TS_0 instead ?

>                  p_sys->i_dts += (int64_t)((double)1000000.0 / p_sys->f_fps);
>              }
>  
> @@ -224,67 +225,12 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
>  static void CreateDecodedNAL( uint8_t **pp_ret, int *pi_ret,
>                                const uint8_t *src, int i_src )
>  {
> -    const uint8_t *end = &src[i_src];
>      uint8_t *dst = malloc( i_src );
>      if( !dst )
>          return;
>  
>      *pp_ret = dst;

Make CreateDecodedNal return uint8_t * instead?

> -
> -    if( dst )
> -    {
> -        while( src < end )
> -        {
> -            if( src < end - 3 && src[0] == 0x00 && src[1] == 0x00 &&
> -                src[2] == 0x03 )
> -            {
> -                *dst++ = 0x00;
> -                *dst++ = 0x00;
> -
> -                src += 3;
> -                continue;
> -            }
> -            *dst++ = *src++;
> -        }
> -    }
> -    *pi_ret = dst - *pp_ret;
> -}
> -
> -
> -static void skipProfileTiersLevel( bs_t * bs, int32_t max_sub_layer_minus1 )
> -{
> -    uint8_t sub_layer_profile_present_flag[8];
> -    uint8_t sub_layer_level_present_flag[8];
> -
> -    /* skipping useless fields of the VPS see https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-H.265-201304-I!!PDF-E&type=item */
> -    bs_skip( bs, 2 + 1 + 5 + 32 + 1 + 1 + 1 + 1 + 44 + 8 );
> -
> -    for( int32_t i = 0; i < max_sub_layer_minus1; i++ )
> -    {
> -        sub_layer_profile_present_flag[i] = bs_read1( bs );
> -        sub_layer_level_present_flag[i] = bs_read1( bs );
> -    }
> -
> -    if(max_sub_layer_minus1 > 0)
> -        bs_skip( bs, (8 - max_sub_layer_minus1) * 2 );
> -
> -    for( int32_t i = 0; i < max_sub_layer_minus1; i++ )
> -    {
> -        if( sub_layer_profile_present_flag[i] )
> -            bs_skip( bs, 2 + 1 + 5 + 32 + 1 + 1 + 1 + 1 + 44 );
> -        if( sub_layer_level_present_flag[i] )
> -            bs_skip( bs, 8 );
> -    }
> -}
> -
> -static uint32_t read_ue( bs_t * bs )
> -{
> -    int32_t i = 0;
> -
> -    while( bs_read1( bs ) == 0 && bs->p < bs->p_end && i < 32 )
> -        i++;
> -
> -    return (1 << i) - 1 + bs_read( bs, i );
> +    *pi_ret = nal_decode( src, dst, i_src );
>  }
>  
>  static int32_t getFPS( demux_t *p_demux, block_t * p_block )
> @@ -299,7 +245,7 @@ static int32_t getFPS( demux_t *p_demux, block_t * p_block )
>          return -1;
>  
>      CreateDecodedNAL( &p_decoded_nal, &i_decoded_nal,
> -                              p_block->p_buffer+3, p_block->i_buffer-3 );
> +                              p_block->p_buffer+4, p_block->i_buffer-4);
>  
>      if( !p_decoded_nal )
>          return -1;
> @@ -309,7 +255,7 @@ static int32_t getFPS( demux_t *p_demux, block_t * p_block )
>      int32_t max_sub_layer_minus1 = bs_read( &bs, 3 );
>      bs_skip( &bs, 17 );
>  
> -    skipProfileTiersLevel( &bs, max_sub_layer_minus1 );
> +    hevc_skip_profile_tiers_level( &bs, max_sub_layer_minus1 );
>  
>      int32_t vps_sub_layer_ordering_info_present_flag = bs_read1( &bs );
>      int32_t i = vps_sub_layer_ordering_info_present_flag? 0 : max_sub_layer_minus1;
> diff --git a/modules/demux/mpeg/mpeg_parser_helpers.h b/modules/demux/mpeg/mpeg_parser_helpers.h
> new file mode 100644
> index 0000000..f8522e8
> --- /dev/null
> +++ b/modules/demux/mpeg/mpeg_parser_helpers.h
> @@ -0,0 +1,81 @@
> +/*****************************************************************************
> + * packetizer_helper.h: Packetizer helpers
> + *****************************************************************************
> + * Copyright (C) 2014 VLC authors and VideoLAN
> + * $Id$
> + *
> + * Authors: Denis Charmet <typx 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 MPEG_PARSER_HELPERS_H
> +#define MPEG_PARSER_HELPERS_H
> +#include <stdint.h>
> +#include <vlc_bits.h>
> +
> +static inline void hevc_skip_profile_tiers_level( bs_t * bs, int32_t max_sub_layer_minus1 )
> +{
> +    uint8_t sub_layer_profile_present_flag[8];
> +    uint8_t sub_layer_level_present_flag[8];
> +
> +    /* skipping useless fields of the VPS see https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-H.265-201304-I!!PDF-E&type=item */
> +    bs_skip( bs, 2 + 1 + 5 + 32 + 1 + 1 + 1 + 1 + 44 + 8 );
> +
> +    for( int32_t i = 0; i < max_sub_layer_minus1; i++ )
> +    {
> +        sub_layer_profile_present_flag[i] = bs_read1( bs );
> +        sub_layer_level_present_flag[i] = bs_read1( bs );
> +    }
> +
> +    if(max_sub_layer_minus1 > 0)
> +        bs_skip( bs, (8 - max_sub_layer_minus1) * 2 );
> +
> +    for( int32_t i = 0; i < max_sub_layer_minus1; i++ )
> +    {
> +        if( sub_layer_profile_present_flag[i] )
> +            bs_skip( bs, 2 + 1 + 5 + 32 + 1 + 1 + 1 + 1 + 44 );
> +        if( sub_layer_level_present_flag[i] )
> +            bs_skip( bs, 8 );
> +    }
> +}
> +
> +static inline uint32_t read_ue( bs_t * bs )
> +{
> +    int32_t i = 0;
> +
> +    while( bs_read1( bs ) == 0 && bs->p < bs->p_end && i < 32 )
> +        i++;
> +
> +    return (1 << i) - 1 + bs_read( bs, i );
> +}
> +
> +
> +static inline size_t nal_decode(uint8_t * p_src, uint8_t * p_dst, size_t i_size)
> +{
> +    size_t j = 0;
> +    for (size_t i = 0; i < i_size; i++) {
> +        if (i < i_size - 3 &&
> +            p_src[i] == 0 && p_src[i+1] == 0 && p_src[i+2] == 3) {
> +            p_dst[j++] = 0;
> +            p_dst[j++] = 0;
> +            i += 2;
> +            continue;
> +        }
> +        p_dst[j++] = p_src[i];
> +    }
> +    return j;
> +}
> +
> +#endif /*MPEG_PARSER_HELPERS_H*/
> diff --git a/modules/mux/Modules.am b/modules/mux/Modules.am
> index 255c939..0283ae3 100644
> --- a/modules/mux/Modules.am
> +++ b/modules/mux/Modules.am
> @@ -1,7 +1,7 @@
>  SOURCES_mux_dummy = dummy.c
>  SOURCES_mux_avi = avi.c
>  SOURCES_mux_ogg = ogg.c
> -SOURCES_mux_mp4 = mp4.c
> +SOURCES_mux_mp4 = mp4.c ../demux/mpeg/mpeg_parser_helpers.h
>  SOURCES_mux_asf = asf.c ../demux/asf/libasf_guid.h
>  SOURCES_mux_wav = wav.c
>  SOURCES_mux_mpjpeg = mpjpeg.c
> diff --git a/modules/mux/mp4.c b/modules/mux/mp4.c
> index 156ecd1..627c36f 100644
> --- a/modules/mux/mp4.c
> +++ b/modules/mux/mp4.c
> @@ -40,6 +40,8 @@
>  #include <vlc_iso_lang.h>
>  #include <vlc_meta.h>
>  
> +#include "../demux/mpeg/mpeg_parser_helpers.h"
> +
>  /*****************************************************************************
>   * Module descriptor
>   *****************************************************************************/
> @@ -448,7 +450,8 @@ static int Mux(sout_mux_t *p_mux)
>          block_t *p_data;
>          do {
>              p_data = block_FifoGet(p_input->p_fifo);
> -            if (p_stream->fmt.i_codec == VLC_CODEC_H264)
> +            if (p_stream->fmt.i_codec == VLC_CODEC_H264 ||
> +                p_stream->fmt.i_codec == VLC_CODEC_HEVC)
>                  p_data = ConvertAVC1(p_data);

Maybe function name should be changed?

>              else if (p_stream->fmt.i_codec == VLC_CODEC_SUBT)
>                  p_data = ConvertSUBT(p_data);
> @@ -759,13 +762,272 @@ static bo_t *GetD263Tag(void)
>      return d263;
>  }
>  
> +
> +/*
> +The following table comes from iso/iec 14496-15 3rd edition
> +
> +aligned(8) class HEVCDecoderConfigurationRecord {
> +    unsigned int(8) configurationVersion = 1;
> +    unsigned int(2) general_profile_space;
> +    unsigned int(1) general_tier_flag;
> +    unsigned int(5) general_profile_idc;
> +    unsigned int(32) general_profile_compatibility_flags;
> +    unsigned int(48) general_constraint_indicator_flags;
> +    unsigned int(8) general_level_idc;
> +    bit(4) reserved = ‘1111’b;
> +    unsigned int(12) min_spatial_segmentation_idc;
> +    bit(6) reserved = ‘111111’b;
> +    unsigned int(2) parallelismType;
> +    bit(6) reserved = ‘111111’b;
> +    unsigned int(2) chromaFormat;
> +    bit(5) reserved = ‘11111’b;
> +    unsigned int(3) bitDepthLumaMinus8;
> +    bit(5) reserved = ‘11111’b;
> +    unsigned int(3) bitDepthChromaMinus8;
> +    bit(16) avgFrameRate;
> +    bit(2) constantFrameRate;
> +    bit(3) numTemporalLayers;
> +    bit(1) temporalIdNested;
> +    unsigned int(2) lengthSizeMinusOne;
> +    unsigned int(8) numOfArrays;
> +    for (j=0; j < numOfArrays; j++) {
> +        bit(1) array_completeness;
> +        unsigned int(1) reserved = 0;
> +        unsigned int(6) NAL_unit_type;
> +        unsigned int(16) numNalus;
> +        for (i=0; i< numNalus; i++) {
> +            unsigned int(16) nalUnitLength;
> +            bit(8*nalUnitLength) nalUnit;
> +        }
> +    }
> +}
> +*/

Is this description your own work ?

> +
> +static void hevcParseVPS(uint8_t * p_buffer, size_t i_buffer, uint8_t *general,
> +                         uint8_t * numTemporalLayer, bool * temporalIdNested)
> +{
> +    const size_t i_decoded_nal_size = 512;

Magic value?

> +    uint8_t p_dec_nal[i_decoded_nal_size];
> +    size_t i_size = (i_buffer < i_decoded_nal_size)?i_buffer:i_decoded_nal_size;
> +    nal_decode(p_buffer, p_dec_nal, i_size);
> +
> +    /* first two bytes are the NAL header 3rd and 4th are:

Comma before "3rd" ?

> +        vps_video_parameter_set_id(4)
> +        vps_reserved_3_2bis(2)
> +        vps_max_layers_minus1(6)
> +        vps_max_sub_layers_minus1(3)
> +        vps_temporal_id_nesting_flags
> +    */
> +    *numTemporalLayer =  ((p_dec_nal[3] & 0x0E) >> 1) + 1;
> +    *temporalIdNested = (bool)(p_dec_nal[3] & 0x01);
> +
> +    /* 5th & 6th are reserved 0xffff */
> +    /* copy the first 12 bytes of profile tier */
> +    memcpy(general, &p_dec_nal[6], 12);
> +}
> +
> +static void hevcParseSPS(uint8_t * p_buffer, size_t i_buffer, uint8_t * chroma_idc,
> +                         uint8_t *bit_depth_luma_minus8, uint8_t *bit_depth_chroma_minus8)
> +{
> +    const size_t i_decoded_nal_size = 512;
> +    uint8_t p_dec_nal[i_decoded_nal_size];
> +    size_t i_size = (i_buffer < i_decoded_nal_size)?i_buffer-2:i_decoded_nal_size;
> +    nal_decode(p_buffer+2, p_dec_nal, i_size);
> +    bs_t bs;
> +    bs_init(&bs, p_dec_nal, i_size);
> +
> +    /* skip vps id */
> +    bs_skip(&bs, 4);
> +    uint32_t sps_max_sublayer_minus1 = bs_read(&bs, 3);
> +
> +    /* skip nesting flag */
> +    bs_skip(&bs, 1);
> +
> +    hevc_skip_profile_tiers_level(&bs, sps_max_sublayer_minus1);
> +
> +    /* skip sps id */
> +    (void) read_ue( &bs );
> +
> +    *chroma_idc = read_ue(&bs);
> +    if (*chroma_idc == 3)
> +        bs_skip(&bs, 1);
> +
> +    /* skip width and heigh */
> +    (void) read_ue( &bs );
> +    (void) read_ue( &bs );
> +
> +    uint32_t conformance_window_flag = bs_read1(&bs);
> +    if (conformance_window_flag) {
> +        /* skip offsets*/
> +        (void) read_ue(&bs);
> +        (void) read_ue(&bs);
> +        (void) read_ue(&bs);
> +        (void) read_ue(&bs);
> +    }
> +    *bit_depth_luma_minus8 = read_ue(&bs);
> +    *bit_depth_chroma_minus8 = read_ue(&bs);
> +}
> +
>  static bo_t *GetHvcCTag(mp4_stream_t *p_stream)
>  {
>      bo_t *hvcC = box_new("hvcC");
> +    if (p_stream->fmt.i_extra > 0) {

if (!p_stream->fmt.i_extra)
	return hvcC;

> +        struct nal {
> +            size_t i_buffer;
> +            uint8_t * p_buffer;
> +        };
> +
> +        /* According to the specification HEVC stream can have
> +         * 16 vps id and an "unlimited" number of sps and pps id using ue(v) id*/
> +        struct nal p_vps[16], *p_sps = NULL, *p_pps = NULL, *p_sei = NULL,
> +                   *p_nal = NULL;
> +        size_t i_vps = 0, i_sps = 0, i_pps = 0, i_sei = 0;
> +        uint8_t i_num_arrays = 0;
> +
> +        uint8_t * p_buffer = p_stream->fmt.p_extra;
> +        size_t i_buffer = p_stream->fmt.i_extra;
> +
> +        uint8_t general_configuration[12] = {0};
> +        uint8_t i_numTemporalLayer;
> +        uint8_t i_chroma_idc = 1;
> +        uint8_t i_bit_depth_luma_minus8 = 0;
> +        uint8_t i_bit_depth_chroma_minus8 = 0;
> +        bool b_temporalIdNested;
> +
> +        uint32_t cmp = 0xFFFFFFFF;
> +        while (i_buffer) {
> +            /* look for start code 0X0000001 */
> +            while (i_buffer) {
> +                cmp = (cmp << 8) | *p_buffer;
> +                if((cmp ^ UINT32_C(0x100)) <= UINT32_C(0xFF))
> +                    break;
> +                p_buffer++;
> +                i_buffer--;
> +            }
> +            if (p_nal)
> +                p_nal->i_buffer = p_buffer - p_nal->p_buffer - ((i_buffer)?3:0);
> +
> +            switch (*p_buffer & 0x72) {
> +            /* VPS */
> +            case 0x40:
> +                p_nal = &p_vps[i_vps++];
> +                p_nal->p_buffer = p_buffer;
> +                /* Only keep the general profile from the first VPS
> +                 * if there are several (this shouldn't happen so soon) */
> +                if (i_vps == 1) {
> +                    hevcParseVPS(p_buffer, i_buffer, general_configuration,
> +                                 &i_numTemporalLayer, &b_temporalIdNested);
> +                    i_num_arrays++;
> +                }
> +                break;
> +            /* SPS */
> +            case 0x42: {
> +                struct nal * p_tmp =  realloc(p_sps, sizeof(struct nal) * (i_sps + 1));
> +                if (!p_tmp)
> +                    break;
> +                p_sps = p_tmp;
> +                p_nal = &p_sps[i_sps++];
> +                p_nal->p_buffer = p_buffer;
> +                if (i_sps == 1 && i_buffer > 15) {
> +                    /* Get Chroma_idc and bitdepths */
> +                    hevcParseSPS(p_buffer, i_buffer, &i_chroma_idc,
> +                                &i_bit_depth_luma_minus8, &i_bit_depth_chroma_minus8);
> +                    i_num_arrays++;
> +                }
> +                break;
> +            }
> +            /* PPS */
> +            case 0x44: {
> +                struct nal * p_tmp =  realloc(p_pps, sizeof(struct nal) * (i_pps + 1));
> +                if (!p_tmp)
> +                    break;
> +                p_pps = p_tmp;
> +                p_nal = &p_pps[i_pps++];
> +                p_nal->p_buffer = p_buffer;
> +                if (i_pps == 1)
> +                    i_num_arrays++;
> +                break;
> +            }
> +            /* SEI */
> +            case 0x4E:
> +            case 0x50: {
> +                struct nal * p_tmp =  realloc(p_sei, sizeof(struct nal) * (i_sei + 1));
> +                if (!p_tmp)
> +                    break;
> +                p_sei = p_tmp;
> +                p_nal = &p_sei[i_sei++];
> +                p_nal->p_buffer = p_buffer;
> +                if(i_sei == 1)
> +                    i_num_arrays++;
> +                break;
> +            }
> +            default:
> +                p_nal = NULL;
> +                break;
> +            }
> +        }
> +        bo_add_8(hvcC, 0x01);
> +        bo_add_mem(hvcC, 12, general_configuration);
> +        /* Don't set min spatial segmentation */
> +        bo_add_16be(hvcC, 0xF000);
> +        /* Don't set parallelism type since segmentation isn't set */
> +        bo_add_8(hvcC, 0xFC);
> +        bo_add_8(hvcC, (0xFC | (i_chroma_idc & 0x03)));
> +        bo_add_8(hvcC, (0xF8 | (i_bit_depth_luma_minus8 & 0x07)));
> +        bo_add_8(hvcC, (0xF8 | (i_bit_depth_chroma_minus8 & 0x07)));
> +
> +        /* Don't set framerate */
> +        bo_add_16be(hvcC, 0x0000);
> +        /* Force NAL size of 4 bytes that replace the startcode */
> +        bo_add_8(hvcC, (((i_numTemporalLayer & 0x07) << 3) |
> +                        (b_temporalIdNested << 2) | 0x03));
> +        bo_add_8(hvcC, i_num_arrays);
> +
> +        if (i_vps)
> +        {
> +            /* Write VPS without forcing array_completeness */
> +            bo_add_8(hvcC, 32);
> +            bo_add_16be(hvcC, i_vps);
> +            for (size_t i = 0; i < i_vps; i++) {
> +                p_nal = &p_vps[i];
> +                bo_add_16be(hvcC, p_nal->i_buffer);
> +                bo_add_mem(hvcC, p_nal->i_buffer, p_nal->p_buffer);
> +            }
> +        }
> +
> +        if (i_sps) {
> +            /* Write SPS without forcing array_completeness */
> +            bo_add_8(hvcC, 33);
> +            bo_add_16be(hvcC, i_sps);
> +            for (size_t i = 0; i < i_sps; i++) {
> +                p_nal = &p_sps[i];
> +                bo_add_16be(hvcC, p_nal->i_buffer);
> +                bo_add_mem(hvcC, p_nal->i_buffer, p_nal->p_buffer);
> +            }
> +        }
>  
> -    if (p_stream->fmt.i_extra > 0)
> -        bo_add_mem(hvcC, p_stream->fmt.i_extra, p_stream->fmt.p_extra);
> +        if (i_pps) {
> +            /* Write PPS without forcing array_completeness */
> +            bo_add_8(hvcC, 34);
> +            bo_add_16be(hvcC, i_pps);
> +            for (size_t i = 0; i < i_pps; i++) {
> +                p_nal = &p_pps[i];
> +                bo_add_16be(hvcC, p_nal->i_buffer);
> +                bo_add_mem(hvcC, p_nal->i_buffer, p_nal->p_buffer);
> +            }
> +        }
>  
> +        if (i_sei) {
> +            /* Write SEI without forcing array_completeness */
> +            bo_add_8(hvcC, 39);
> +            bo_add_16be(hvcC, i_sei);
> +            for (size_t i = 0; i < i_sei; i++) {
> +                p_nal = &p_sei[i];
> +                bo_add_16be(hvcC, p_nal->i_buffer);
> +            bo_add_mem(hvcC, p_nal->i_buffer, p_nal->p_buffer);
> +            }
> +        }
> +    }
>      return hvcC;
>  }
>  
> diff --git a/modules/packetizer/hevc.c b/modules/packetizer/hevc.c
> index 58b207b..a905f8f 100644
> --- a/modules/packetizer/hevc.c
> +++ b/modules/packetizer/hevc.c
> @@ -124,7 +124,7 @@ static int Open(vlc_object_t *p_this)
>  
>      packetizer_Init(&p_dec->p_sys->packetizer,
>                      p_hevc_startcode, sizeof(p_hevc_startcode),
> -                    NULL, 0, 0,
> +                    p_hevc_startcode, 1, 5,
>                      PacketizeReset, PacketizeParse, PacketizeValidate, p_dec);
>  
>      /* Copy properties */
> @@ -185,7 +185,7 @@ static block_t *PacketizeParse(void *p_private, bool *pb_ts_used, block_t *p_blo
>          p_block->i_buffer--;
>  
>      bs_t bs;
> -    bs_init(&bs, p_block->p_buffer+3, p_block->i_buffer-3);
> +    bs_init(&bs, p_block->p_buffer+4, p_block->i_buffer-4);
>  
>      /* Get NALU type */
>      uint32_t forbidden_zero_bit = bs_read1(&bs);
> 



More information about the vlc-devel mailing list