Commit a0f65bae authored by Francois Cartegnie's avatar Francois Cartegnie

packetizer: add hxxx_nal.h for avc/hevc rbsp conversions

parent 9b748033
...@@ -166,7 +166,8 @@ demux_LTLIBRARIES += libes_plugin.la ...@@ -166,7 +166,8 @@ demux_LTLIBRARIES += libes_plugin.la
libh264_plugin_la_SOURCES = demux/mpeg/h264.c libh264_plugin_la_SOURCES = demux/mpeg/h264.c
demux_LTLIBRARIES += libh264_plugin.la demux_LTLIBRARIES += libh264_plugin.la
libhevc_plugin_la_SOURCES = demux/mpeg/hevc.c demux/mpeg/mpeg_parser_helpers.h libhevc_plugin_la_SOURCES = demux/mpeg/hevc.c demux/mpeg/mpeg_parser_helpers.h \
packetizer/hxxx_nal.h
demux_LTLIBRARIES += libhevc_plugin.la demux_LTLIBRARIES += libhevc_plugin.la
libmkv_plugin_la_SOURCES = \ libmkv_plugin_la_SOURCES = \
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <vlc_bits.h> #include <vlc_bits.h>
#include "mpeg_parser_helpers.h" #include "mpeg_parser_helpers.h"
#include "../packetizer/hxxx_nal.h"
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
...@@ -223,32 +224,19 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) ...@@ -223,32 +224,19 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
0, 1, i_query, args ); 0, 1, i_query, args );
} }
static uint8_t * CreateDecodedNAL( int *pi_ret,
const uint8_t *src, int i_src )
{
uint8_t *dst = malloc( i_src );
if( !dst )
return NULL;
*pi_ret = nal_to_rbsp( src, dst, i_src );
return dst;
}
static int32_t getFPS( demux_t *p_demux, block_t * p_block ) static int32_t getFPS( demux_t *p_demux, block_t * p_block )
{ {
demux_sys_t *p_sys = p_demux->p_sys; demux_sys_t *p_sys = p_demux->p_sys;
bs_t bs; bs_t bs;
uint8_t * p_decoded_nal; uint8_t * p_decoded_nal;
int i_decoded_nal; size_t i_decoded_nal;
if( p_block->i_buffer < 5 ) if( p_block->i_buffer < 5 )
return -1; return -1;
p_decoded_nal = CreateDecodedNAL(&i_decoded_nal, p_decoded_nal = hxxx_ep3b_to_rbsp(p_block->p_buffer+4, p_block->i_buffer-4,
p_block->p_buffer+4, p_block->i_buffer-4); &i_decoded_nal);
if( !p_decoded_nal ) if( !p_decoded_nal )
return -1; return -1;
......
...@@ -51,21 +51,4 @@ static inline void hevc_skip_profile_tiers_level( bs_t * bs, int32_t max_sub_lay ...@@ -51,21 +51,4 @@ static inline void hevc_skip_profile_tiers_level( bs_t * bs, int32_t max_sub_lay
} }
} }
/* Discards emulation prevention three bytes */
static inline size_t nal_to_rbsp(const 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*/ #endif /*MPEG_PARSER_HELPERS_H*/
...@@ -6,7 +6,7 @@ libmux_asf_plugin_la_SOURCES = mux/asf.c demux/asf/libasf_guid.h ...@@ -6,7 +6,7 @@ libmux_asf_plugin_la_SOURCES = mux/asf.c demux/asf/libasf_guid.h
libmux_avi_plugin_la_SOURCES = mux/avi.c libmux_avi_plugin_la_SOURCES = mux/avi.c
libmux_mp4_plugin_la_SOURCES = mux/mp4/mp4.c \ libmux_mp4_plugin_la_SOURCES = mux/mp4/mp4.c \
mux/mp4/libmp4mux.c mux/mp4/libmp4mux.h \ mux/mp4/libmp4mux.c mux/mp4/libmp4mux.h \
demux/mpeg/mpeg_parser_helpers.h demux/mp4/libmp4.h \ packetizer/hxxx_nal.h demux/mp4/libmp4.h \
packetizer/h264_nal.c packetizer/h264_nal.h packetizer/h264_nal.c packetizer/h264_nal.h
libmux_mpjpeg_plugin_la_SOURCES = mux/mpjpeg.c libmux_mpjpeg_plugin_la_SOURCES = mux/mpjpeg.c
libmux_ps_plugin_la_SOURCES = \ libmux_ps_plugin_la_SOURCES = \
......
...@@ -22,8 +22,8 @@ ...@@ -22,8 +22,8 @@
*****************************************************************************/ *****************************************************************************/
#include "libmp4mux.h" #include "libmp4mux.h"
#include "../demux/mp4/libmp4.h" /* flags */ #include "../demux/mp4/libmp4.h" /* flags */
#include "../demux/mpeg/mpeg_parser_helpers.h" /* nal rbsp */
#include "../packetizer/h264_nal.h" /* h264_get_spspps */ #include "../packetizer/h264_nal.h" /* h264_get_spspps */
#include "../packetizer/hxxx_nal.h"
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
# include "config.h" # include "config.h"
...@@ -496,10 +496,13 @@ static bo_t *GetD263Tag(void) ...@@ -496,10 +496,13 @@ static bo_t *GetD263Tag(void)
static void hevcParseVPS(uint8_t * p_buffer, size_t i_buffer, uint8_t *general, static void hevcParseVPS(uint8_t * p_buffer, size_t i_buffer, uint8_t *general,
uint8_t * numTemporalLayer, bool * temporalIdNested) uint8_t * numTemporalLayer, bool * temporalIdNested)
{ {
const size_t i_decoded_nal_size = 512; size_t i_decoded_nal_size;
uint8_t p_dec_nal[i_decoded_nal_size]; uint8_t *p_dec_nal = hxxx_ep3b_to_rbsp(p_buffer, i_buffer, &i_decoded_nal_size);
size_t i_size = (i_buffer < i_decoded_nal_size)?i_buffer:i_decoded_nal_size; if(!p_dec_nal || i_decoded_nal_size < 19)
nal_to_rbsp(p_buffer, p_dec_nal, i_size); {
free(p_dec_nal);
return;
}
/* first two bytes are the NAL header, 3rd and 4th are: /* first two bytes are the NAL header, 3rd and 4th are:
vps_video_parameter_set_id(4) vps_video_parameter_set_id(4)
...@@ -514,17 +517,22 @@ static void hevcParseVPS(uint8_t * p_buffer, size_t i_buffer, uint8_t *general, ...@@ -514,17 +517,22 @@ static void hevcParseVPS(uint8_t * p_buffer, size_t i_buffer, uint8_t *general,
/* 5th & 6th are reserved 0xffff */ /* 5th & 6th are reserved 0xffff */
/* copy the first 12 bytes of profile tier */ /* copy the first 12 bytes of profile tier */
memcpy(general, &p_dec_nal[6], 12); memcpy(general, &p_dec_nal[6], 12);
free(p_dec_nal);
} }
static void hevcParseSPS(uint8_t * p_buffer, size_t i_buffer, uint8_t * chroma_idc, 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) uint8_t *bit_depth_luma_minus8, uint8_t *bit_depth_chroma_minus8)
{ {
const size_t i_decoded_nal_size = 512; if(i_buffer < 2)
uint8_t p_dec_nal[i_decoded_nal_size]; return;
size_t i_size = (i_buffer < i_decoded_nal_size)?i_buffer-2:i_decoded_nal_size;
nal_to_rbsp(p_buffer+2, p_dec_nal, i_size); size_t i_decoded_nal_size;
uint8_t *p_dec_nal = hxxx_ep3b_to_rbsp(p_buffer + 2, i_buffer - 2, &i_decoded_nal_size);
if(!p_dec_nal)
return;
bs_t bs; bs_t bs;
bs_init(&bs, p_dec_nal, i_size); bs_init(&bs, p_dec_nal, i_decoded_nal_size);
/* skip vps id */ /* skip vps id */
bs_skip(&bs, 4); bs_skip(&bs, 4);
...@@ -556,6 +564,8 @@ static void hevcParseSPS(uint8_t * p_buffer, size_t i_buffer, uint8_t * chroma_i ...@@ -556,6 +564,8 @@ static void hevcParseSPS(uint8_t * p_buffer, size_t i_buffer, uint8_t * chroma_i
} }
*bit_depth_luma_minus8 = bs_read_ue(&bs); *bit_depth_luma_minus8 = bs_read_ue(&bs);
*bit_depth_chroma_minus8 = bs_read_ue(&bs); *bit_depth_chroma_minus8 = bs_read_ue(&bs);
free(p_dec_nal);
} }
static bo_t *GetHvcCTag(es_format_t *p_fmt) static bo_t *GetHvcCTag(es_format_t *p_fmt)
......
...@@ -6,13 +6,13 @@ libpacketizer_mpeg4video_plugin_la_SOURCES = packetizer/mpeg4video.c ...@@ -6,13 +6,13 @@ libpacketizer_mpeg4video_plugin_la_SOURCES = packetizer/mpeg4video.c
libpacketizer_mpeg4audio_plugin_la_SOURCES = packetizer/mpeg4audio.c libpacketizer_mpeg4audio_plugin_la_SOURCES = packetizer/mpeg4audio.c
libpacketizer_h264_plugin_la_SOURCES = \ libpacketizer_h264_plugin_la_SOURCES = \
packetizer/h264_nal.c packetizer/h264_nal.h \ packetizer/h264_nal.c packetizer/h264_nal.h \
packetizer/h264.c packetizer/h264.c packetizer/hxxx_nal.h
libpacketizer_vc1_plugin_la_SOURCES = packetizer/vc1.c libpacketizer_vc1_plugin_la_SOURCES = packetizer/vc1.c
libpacketizer_mlp_plugin_la_SOURCES = packetizer/mlp.c libpacketizer_mlp_plugin_la_SOURCES = packetizer/mlp.c
libpacketizer_dirac_plugin_la_SOURCES = packetizer/dirac.c libpacketizer_dirac_plugin_la_SOURCES = packetizer/dirac.c
libpacketizer_flac_plugin_la_SOURCES = packetizer/flac.c libpacketizer_flac_plugin_la_SOURCES = packetizer/flac.c
libpacketizer_hevc_plugin_la_SOURCES = packetizer/hevc.c \ libpacketizer_hevc_plugin_la_SOURCES = packetizer/hevc.c \
packetizer/hevc_nal.h packetizer/hevc_nal.h packetizer/hxxx_nal.h
libpacketizer_avparser_plugin_la_SOURCES = packetizer/avparser.c \ libpacketizer_avparser_plugin_la_SOURCES = packetizer/avparser.c \
packetizer/avparser.h \ packetizer/avparser.h \
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <vlc_bits.h> #include <vlc_bits.h>
#include "../codec/cc.h" #include "../codec/cc.h"
#include "h264_nal.h" #include "h264_nal.h"
#include "hxxx_nal.h"
#include "packetizer_helper.h" #include "packetizer_helper.h"
/***************************************************************************** /*****************************************************************************
...@@ -161,7 +162,7 @@ static block_t *CreateAnnexbNAL( decoder_t *, const uint8_t *p, int ); ...@@ -161,7 +162,7 @@ static block_t *CreateAnnexbNAL( decoder_t *, const uint8_t *p, int );
static block_t *OutputPicture( decoder_t *p_dec ); static block_t *OutputPicture( decoder_t *p_dec );
static void PutSPS( decoder_t *p_dec, block_t *p_frag ); static void PutSPS( decoder_t *p_dec, block_t *p_frag );
static void PutPPS( decoder_t *p_dec, block_t *p_frag ); static void PutPPS( decoder_t *p_dec, block_t *p_frag );
static void ParseSlice( decoder_t *p_dec, bool *pb_new_picture, slice_t *p_slice, static bool ParseSlice( decoder_t *p_dec, bool *pb_new_picture, slice_t *p_slice,
int i_nal_ref_idc, int i_nal_type, const block_t *p_frag ); int i_nal_ref_idc, int i_nal_type, const block_t *p_frag );
static void ParseSei( decoder_t *, block_t * ); static void ParseSei( decoder_t *, block_t * );
...@@ -601,15 +602,16 @@ static block_t *ParseNALBlock( decoder_t *p_dec, bool *pb_ts_used, block_t *p_fr ...@@ -601,15 +602,16 @@ static block_t *ParseNALBlock( decoder_t *p_dec, bool *pb_ts_used, block_t *p_fr
slice_t slice; slice_t slice;
bool b_new_picture; bool b_new_picture;
ParseSlice( p_dec, &b_new_picture, &slice, i_nal_ref_idc, i_nal_type, p_frag ); if(ParseSlice( p_dec, &b_new_picture, &slice, i_nal_ref_idc, i_nal_type, p_frag ))
{
/* */ /* */
if( b_new_picture && p_sys->b_slice ) if( b_new_picture && p_sys->b_slice )
p_pic = OutputPicture( p_dec ); p_pic = OutputPicture( p_dec );
/* */ /* */
p_sys->slice = slice; p_sys->slice = slice;
p_sys->b_slice = true; p_sys->b_slice = true;
}
} }
else if( i_nal_type == H264_NAL_SPS ) else if( i_nal_type == H264_NAL_SPS )
{ {
...@@ -891,7 +893,7 @@ static void PutPPS( decoder_t *p_dec, block_t *p_frag ) ...@@ -891,7 +893,7 @@ static void PutPPS( decoder_t *p_dec, block_t *p_frag )
p_sys->pp_pps[pps.i_id] = p_frag; p_sys->pp_pps[pps.i_id] = p_frag;
} }
static void ParseSlice( decoder_t *p_dec, bool *pb_new_picture, slice_t *p_slice, static bool ParseSlice( decoder_t *p_dec, bool *pb_new_picture, slice_t *p_slice,
int i_nal_ref_idc, int i_nal_type, const block_t *p_frag ) int i_nal_ref_idc, int i_nal_type, const block_t *p_frag )
{ {
decoder_sys_t *p_sys = p_dec->p_sys; decoder_sys_t *p_sys = p_dec->p_sys;
...@@ -901,9 +903,14 @@ static void ParseSlice( decoder_t *p_dec, bool *pb_new_picture, slice_t *p_slice ...@@ -901,9 +903,14 @@ static void ParseSlice( decoder_t *p_dec, bool *pb_new_picture, slice_t *p_slice
slice_t slice; slice_t slice;
bs_t s; bs_t s;
if(p_frag->i_buffer < 6)
return false;
/* do not convert the whole frame */ /* do not convert the whole frame */
CreateRbspFromNAL( &pb_dec, &i_dec, &p_frag->p_buffer[5], pb_dec = hxxx_ep3b_to_rbsp(&p_frag->p_buffer[5], __MIN( p_frag->i_buffer - 5, 60 ), &i_dec);
__MIN( p_frag->i_buffer - 5, 60 ) ); if(!pb_dec)
return false;
bs_init( &s, pb_dec, i_dec ); bs_init( &s, pb_dec, i_dec );
/* first_mb_in_slice */ /* first_mb_in_slice */
...@@ -999,6 +1006,8 @@ static void ParseSlice( decoder_t *p_dec, bool *pb_new_picture, slice_t *p_slice ...@@ -999,6 +1006,8 @@ static void ParseSlice( decoder_t *p_dec, bool *pb_new_picture, slice_t *p_slice
/* */ /* */
*pb_new_picture = b_pic; *pb_new_picture = b_pic;
*p_slice = slice; *p_slice = slice;
return true;
} }
static void ParseSei( decoder_t *p_dec, block_t *p_frag ) static void ParseSei( decoder_t *p_dec, block_t *p_frag )
...@@ -1007,8 +1016,11 @@ static void ParseSei( decoder_t *p_dec, block_t *p_frag ) ...@@ -1007,8 +1016,11 @@ static void ParseSei( decoder_t *p_dec, block_t *p_frag )
uint8_t *pb_dec; uint8_t *pb_dec;
size_t i_dec = 0; size_t i_dec = 0;
if( p_frag->i_buffer < 6 )
return;
/* */ /* */
CreateRbspFromNAL( &pb_dec, &i_dec, &p_frag->p_buffer[5], p_frag->i_buffer - 5 ); pb_dec = hxxx_ep3b_to_rbsp( &p_frag->p_buffer[5], p_frag->i_buffer - 5, &i_dec );
if( !pb_dec ) if( !pb_dec )
return; return;
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
*****************************************************************************/ *****************************************************************************/
#include "h264_nal.h" #include "h264_nal.h"
#include "hxxx_nal.h"
#include <vlc_boxes.h> #include <vlc_boxes.h>
#include <limits.h> #include <limits.h>
...@@ -425,8 +426,7 @@ int h264_parse_sps( const uint8_t *p_sps_buf, int i_sps_size, ...@@ -425,8 +426,7 @@ int h264_parse_sps( const uint8_t *p_sps_buf, int i_sps_size,
return -1; return -1;
memset( p_sps, 0, sizeof(struct h264_nal_sps) ); memset( p_sps, 0, sizeof(struct h264_nal_sps) );
CreateRbspFromNAL( &pb_dec, &i_dec, &p_sps_buf[5], pb_dec = hxxx_ep3b_to_rbsp( &p_sps_buf[5], i_sps_size - 5, &i_dec );
i_sps_size - 5 );
if( !pb_dec ) if( !pb_dec )
return -1; return -1;
......
...@@ -107,17 +107,6 @@ struct h264_nal_pps ...@@ -107,17 +107,6 @@ struct h264_nal_pps
int i_pic_order_present_flag; int i_pic_order_present_flag;
}; };
static inline void CreateRbspFromNAL( uint8_t **pp_ret, size_t *pi_ret,
const uint8_t *src, int i_src )
{
uint8_t *dst = malloc( i_src );
*pp_ret = dst;
if( dst )
*pi_ret = nal_to_rbsp(src, dst, i_src);
}
/* /*
AnnexB : [\x00] \x00 \x00 \x01 Prefixed NAL AnnexB : [\x00] \x00 \x00 \x01 Prefixed NAL
AVC Sample format : NalLengthSize encoded size prefixed NAL AVC Sample format : NalLengthSize encoded size prefixed NAL
......
/*****************************************************************************
* hxxx_nal.h: Common helpers for AVC/HEVC NALU
*****************************************************************************
* Copyright (C) 2014-2015 VLC authors and VideoLAN
*
* 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 HXXX_NAL_H
#define HXXX_NAL_H
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
/* Discards emulation prevention three bytes */
static inline uint8_t * hxxx_ep3b_to_rbsp(const uint8_t *p_src, size_t i_src, size_t *pi_ret)
{
uint8_t *p_dst;
if(!p_src || !(p_dst = malloc(i_src)))
return NULL;
size_t j = 0;
for (size_t i = 0; i < i_src; i++) {
if (i < i_src - 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];
}
*pi_ret = j;
return p_dst;
}
#endif // HXXX_NAL_H
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment