vlc | branch: master | Francois Cartegnie <[email protected]> | Tue Jan 12 21:34:52 2021 +0100| [29bb1cf43cef818f27b9054009b4bbfd24276e32] | committer: Francois Cartegnie
mux: ts/pes: add proper handling for payload injection currently totally broken with blind double injection of parameters creating empty access units > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=29bb1cf43cef818f27b9054009b4bbfd24276e32 --- modules/mux/Makefile.am | 2 + modules/mux/mpeg/pes.c | 49 +++---------- modules/mux/mpeg/repack.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++ modules/mux/mpeg/repack.h | 23 ++++++ 4 files changed, 216 insertions(+), 38 deletions(-) diff --git a/modules/mux/Makefile.am b/modules/mux/Makefile.am index 581e8a1dd9..876dd2e76a 100644 --- a/modules/mux/Makefile.am +++ b/modules/mux/Makefile.am @@ -18,6 +18,7 @@ libmux_mp4_plugin_la_SOURCES += $(extradata_builder_SOURCES) libmux_mpjpeg_plugin_la_SOURCES = mux/mpjpeg.c libmux_ps_plugin_la_SOURCES = \ mux/mpeg/pes.c mux/mpeg/pes.h \ + mux/mpeg/repack.c mux/mpeg/repack.h \ mux/mpeg/ps.c mux/mpeg/bits.h \ demux/mpeg/timestamps.h libmux_wav_plugin_la_SOURCES = mux/wav.c @@ -40,6 +41,7 @@ mux_LTLIBRARIES += $(LTLIBmux_ogg) libmux_ts_plugin_la_SOURCES = \ mux/mpeg/pes.c mux/mpeg/pes.h \ + mux/mpeg/repack.c mux/mpeg/repack.h \ mux/mpeg/csa.c mux/mpeg/csa.h \ mux/mpeg/streams.h \ mux/mpeg/tables.c mux/mpeg/tables.h \ diff --git a/modules/mux/mpeg/pes.c b/modules/mux/mpeg/pes.c index def7e78b97..242c72f395 100644 --- a/modules/mux/mpeg/pes.c +++ b/modules/mux/mpeg/pes.c @@ -35,6 +35,7 @@ #include <assert.h> #include "pes.h" +#include "repack.h" #include "bits.h" #include "../../demux/mpeg/timestamps.h" @@ -344,44 +345,16 @@ void EStoPES ( block_t **pp_pes, i_max_pes_size = PES_PAYLOAD_SIZE_MAX; } - if( ( p_fmt->i_codec == VLC_CODEC_MP4V || - p_fmt->i_codec == VLC_CODEC_H264 || - p_fmt->i_codec == VLC_CODEC_HEVC) && - p_es->i_flags & BLOCK_FLAG_TYPE_I ) - { - /* For MPEG4 video, add VOL before I-frames, - for H264 add SPS/PPS before keyframes*/ - p_es = block_Realloc( p_es, p_fmt->i_extra, p_es->i_buffer ); - - memcpy( p_es->p_buffer, p_fmt->p_extra, p_fmt->i_extra ); - } - - if( p_fmt->i_codec == VLC_CODEC_H264 ) - { - unsigned offset=2; - while(offset < p_es->i_buffer ) - { - if( p_es->p_buffer[offset-2] == 0 && - p_es->p_buffer[offset-1] == 0 && - p_es->p_buffer[offset] == 1 ) - break; - offset++; - } - offset++; - if( offset+4 <= p_es->i_buffer && - ((p_es->p_buffer[offset] & 0x1f) != 9) ) /* Not AUD */ - { - /* Make similar AUD as libavformat does */ - p_es = block_Realloc( p_es, 6, p_es->i_buffer ); - p_es->p_buffer[0] = 0x00; - p_es->p_buffer[1] = 0x00; - p_es->p_buffer[2] = 0x00; - p_es->p_buffer[3] = 0x01; - p_es->p_buffer[4] = 0x09; /* FIXME: primary_pic_type from SPS/PPS */ - p_es->p_buffer[5] = 0xf0; - } - - } + /* AUD Fixing + * For MPEG4 video, add VOL before I-frames, + * for H264/HEVC add xPS before keyframes */ + p_es = PES_Repack( p_fmt->i_codec, + (const uint8_t *) p_fmt->p_extra, + (p_es->i_flags & BLOCK_FLAG_TYPE_I) ? p_fmt->i_extra : 0, + pp_pes ); + assert(*pp_pes == p_es); + if( !p_es ) + return; int64_t i_dts = 0; int64_t i_pts = 0; diff --git a/modules/mux/mpeg/repack.c b/modules/mux/mpeg/repack.c new file mode 100644 index 0000000000..6afc5178b7 --- /dev/null +++ b/modules/mux/mpeg/repack.c @@ -0,0 +1,180 @@ +/***************************************************************************** + * repack.c: Codec specific formatting for AnnexB multiplexers + ***************************************************************************** + * Copyright (C) 2021 VideoLabs, 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. + *****************************************************************************/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <vlc_common.h> +#include <vlc_block.h> + +#include "repack.h" +#include "../../packetizer/hevc_nal.h" +#include "../../packetizer/h264_nal.h" +#include "../../packetizer/hxxx_nal.h" + +#include <assert.h> + +static void AnnexBInject(block_t **pp_pes, + const uint8_t *p_extra, size_t i_extra, + const uint8_t *p_au, size_t i_au) +{ + if(!i_extra && !i_au) + return; + + *pp_pes = block_Realloc(*pp_pes, + i_extra + i_au, + (*pp_pes)->i_buffer); + if(!*pp_pes) + return; + if(i_au) + memcpy(&(*pp_pes)->p_buffer[0], p_au, i_au); + if(i_extra) + memcpy(&(*pp_pes)->p_buffer[i_au], p_extra, i_extra); +} + + +static void PES_RepackHEVC(block_t **pp_pes, + const uint8_t *p_extra, size_t i_extra) +{ + size_t i_au = 6; + size_t i_aucurrent = 0; + const uint8_t audata[] = { 0x00, 0x00, 0x00, 0x01, 0x46, 0x01 }; + hxxx_iterator_ctx_t ctx; + hxxx_iterator_init(&ctx, (*pp_pes)->p_buffer, (*pp_pes)->i_buffer, 0); + const uint8_t *p_nal; size_t i_nal; + while(hxxx_annexb_iterate_next(&ctx, &p_nal, &i_nal)) + { + if(i_nal < 2) + return; + uint8_t type = hevc_getNALType(p_nal); + if(type < HEVC_NAL_VPS) + break; + switch(type) + { + case HEVC_NAL_AUD: + i_au = 0; + i_aucurrent = 2 + (p_nal - (*pp_pes)->p_buffer); + break; + case HEVC_NAL_VPS: + case HEVC_NAL_PPS: + case HEVC_NAL_SPS: + i_extra = 0; + break; + default: + break; + } + } + + if(i_extra && i_aucurrent) /* strip existing AU for now */ + { + (*pp_pes)->p_buffer += i_aucurrent; + (*pp_pes)->i_buffer -= i_aucurrent; + i_au = 6; + } + + AnnexBInject(pp_pes, p_extra, i_extra, audata, i_au); +} + +static void PES_RepackH264(block_t **pp_pes, + const uint8_t *p_extra, size_t i_extra) +{ + size_t i_au = 6; + size_t i_aucurrent = 0; + const uint8_t audata[] = { 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0 }; + hxxx_iterator_ctx_t ctx; + hxxx_iterator_init(&ctx, (*pp_pes)->p_buffer, (*pp_pes)->i_buffer, 0); + const uint8_t *p_nal; size_t i_nal; + while(hxxx_annexb_iterate_next(&ctx, &p_nal, &i_nal)) + { + if(i_nal < 2) + return; + uint8_t type = p_nal[0]&0x1f; + if(type < H264_NAL_SEI) + break; + switch(type) + { + case H264_NAL_AU_DELIMITER: + i_au = 0; + i_aucurrent = 2 + (p_nal - (*pp_pes)->p_buffer); + break; + case H264_NAL_SPS: + case H264_NAL_PPS: + i_extra = 0; + break; + default: + break; + } + } + + if(i_extra && i_aucurrent) /* strip existing AU for now */ + { + (*pp_pes)->p_buffer += i_aucurrent; + (*pp_pes)->i_buffer -= i_aucurrent; + i_au = 6; + } + + AnnexBInject(pp_pes, p_extra, i_extra, audata, i_au); +} + +static void PES_RepackMP4V(block_t **pp_pes, + const uint8_t *p_extra, size_t i_extra) +{ + hxxx_iterator_ctx_t ctx; + hxxx_iterator_init(&ctx, (*pp_pes)->p_buffer, (*pp_pes)->i_buffer, 0); + const uint8_t *p_nal; size_t i_nal; + while(hxxx_annexb_iterate_next(&ctx, &p_nal, &i_nal)) + { + if(i_nal < 2) + return; + if(p_nal[0] >= 0x30) /* > VOLS */ + break; + if(p_nal[0] >= 0x20 && p_nal[0] == p_extra[3]) /* same VOL */ + i_extra = 0; + } + + AnnexBInject(pp_pes, p_extra, i_extra, NULL, 0); +} + +block_t * PES_Repack(vlc_fourcc_t i_codec, + const uint8_t *p_extra, size_t i_extra, + block_t **pp_pes) +{ + /* safety check for annexb extra */ + if(i_extra < 4 || + (memcmp(p_extra, annexb_startcode4, 4) && + memcmp(&p_extra[1], annexb_startcode3, 3))) + i_extra = 0; + + switch(i_codec) + { + case VLC_CODEC_HEVC: + PES_RepackHEVC(pp_pes, p_extra, i_extra); + break; + case VLC_CODEC_H264: + PES_RepackH264(pp_pes, p_extra, i_extra); + break; + case VLC_CODEC_MP4V: + PES_RepackMP4V(pp_pes, p_extra, i_extra); + break; + default: + break; + } + return *pp_pes; +} diff --git a/modules/mux/mpeg/repack.h b/modules/mux/mpeg/repack.h new file mode 100644 index 0000000000..45b0cd87c1 --- /dev/null +++ b/modules/mux/mpeg/repack.h @@ -0,0 +1,23 @@ +/***************************************************************************** + * repack.h: Codec specific formatting for AnnexB multiplexers + ***************************************************************************** + * Copyright (C) 2011 VideoLabs, 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. + *****************************************************************************/ + +block_t * PES_Repack(vlc_fourcc_t i_codec, + const uint8_t *p_extra, size_t i_extra, + block_t **pp_pes); _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
