diff --git a/modules/MODULES_LIST b/modules/MODULES_LIST index 87d30694a2e6a33b723cdcfd3339a6025e14a2dd..19e0b342bb9857e3a601c9db5a790bec5d91cbe7 100644 --- a/modules/MODULES_LIST +++ b/modules/MODULES_LIST @@ -171,10 +171,9 @@ $Id$ * grain: Grain Video filter * grey_yuv: grayscale to others conversion module * gstdecode: GStreamer based decoder module. - * h264: H264 decoder + * h26x: Raw H264 and HEVC demuxers * hds: HTTP Dynamic Streaming, per Adobe's specs * headphone_channel_mixer: headphone channel mixer with virtual spatialization effect - * hevc: HEVC demuxer * hotkeys: hotkeys control module * hqdn3d: High Quality denoising filter * http: HTTP Network access module diff --git a/modules/demux/Makefile.am b/modules/demux/Makefile.am index 80adf016a11414f2ac09931ac1ed0d810c82b095..a2712135c1636281f5607b24145367734dc9aeb8 100644 --- a/modules/demux/Makefile.am +++ b/modules/demux/Makefile.am @@ -163,11 +163,8 @@ endif libes_plugin_la_SOURCES = demux/mpeg/es.c codec/dts_header.c codec/dts_header.h 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 -demux_LTLIBRARIES += libhevc_plugin.la +libh26x_plugin_la_SOURCES = demux/mpeg/h26x.c +demux_LTLIBRARIES += libh26x_plugin.la libmkv_plugin_la_SOURCES = \ demux/mkv/util.hpp demux/mkv/util.cpp \ diff --git a/modules/demux/mpeg/h264.c b/modules/demux/mpeg/h26x.c similarity index 71% rename from modules/demux/mpeg/h264.c rename to modules/demux/mpeg/h26x.c index e2ea7405e2990271cd53eab3a84e6b0018430aad..7bf3ab935ec20381908e05eda0df30af638976cf 100644 --- a/modules/demux/mpeg/h264.c +++ b/modules/demux/mpeg/h26x.c @@ -1,10 +1,10 @@ /***************************************************************************** - * h264.c : H264 Video demuxer + * h26x.c : raw H264 and HEVC Video demuxers ***************************************************************************** - * Copyright (C) 2002-2004 VLC authors and VideoLAN - * $Id$ + * Copyright (C) 2002-2004, 2014-2015 VLC authors and VideoLAN * * Authors: Laurent Aimar <fenrir@via.ecp.fr> + * Denis Charmet <typx@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 @@ -37,12 +37,12 @@ /***************************************************************************** * Module descriptor *****************************************************************************/ -static int Open ( vlc_object_t * ); +static int OpenH264 ( vlc_object_t * ); +static int OpenHEVC ( vlc_object_t * ); static void Close( vlc_object_t * ); #define FPS_TEXT N_("Frames per Second") -#define FPS_LONGTEXT N_("Desired frame rate for the H264 stream.") - +#define FPS_LONGTEXT N_("Desired frame rate for the stream.") vlc_module_begin () set_shortname( "H264") @@ -51,8 +51,19 @@ vlc_module_begin () set_description( N_("H264 video demuxer" ) ) set_capability( "demux", 0 ) add_float( "h264-fps", 0.0, FPS_TEXT, FPS_LONGTEXT, true ) - set_callbacks( Open, Close ) + set_callbacks( OpenH264, Close ) add_shortcut( "h264" ) + + add_submodule() + set_shortname( "HEVC") + set_category( CAT_INPUT ) + set_subcategory( SUBCAT_INPUT_DEMUX ) + set_description( N_("HEVC/H.265 video demuxer" ) ) + set_capability( "demux", 0 ) + add_float( "hevc-fps", 0.0, FPS_TEXT, FPS_LONGTEXT, true ) + set_callbacks( OpenHEVC, Close ) + add_shortcut( "hevc" ) + vlc_module_end () /***************************************************************************** @@ -72,37 +83,61 @@ struct demux_sys_t static int Demux( demux_t * ); static int Control( demux_t *, int, va_list ); -#define H264_PACKET_SIZE 2048 +#define H26X_PACKET_SIZE 2048 /***************************************************************************** - * Open: initializes demux structures + * Probing *****************************************************************************/ -static int Open( vlc_object_t * p_this ) +static bool ProbeHEVC( const uint8_t *p_peek, size_t i_peek ) +{ + if( i_peek < 5 ) + return false; + + if( (p_peek[4]&0xFE) != 0x40 /* VPS & forbidden zero bit*/ ) + return false; + else + return true; +} + +static bool ProbeH264( const uint8_t *p_peek, size_t i_peek ) +{ + if( i_peek < 5 ) + return false; + const uint8_t i_nal_type = p_peek[4] & 0x1F; + const uint8_t i_ref_idc = p_peek[4] & 0x60; + if( (p_peek[4] & 0x80) || /* reserved 0 */ + i_nal_type == 0 || i_nal_type > 12 || + ( !i_ref_idc && (i_nal_type < 6 || i_nal_type == 7 || i_nal_type == 8) ) || + ( i_ref_idc && (i_nal_type == 6 || i_nal_type >= 9) ) + ) + return false; + else + return true; +} + +/***************************************************************************** + * Shared Open code + *****************************************************************************/ +static int GenericOpen( demux_t *p_demux, const char *psz_module, + vlc_fourcc_t i_codec, + bool(*pf_probe)(const uint8_t *, size_t) ) { - demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; const uint8_t *p_peek; es_format_t fmt; if( stream_Peek( p_demux->s, &p_peek, 5 ) < 5 ) return VLC_EGENERIC; - const uint8_t i_nal_type = p_peek[4] & 0x1F; - const uint8_t i_ref_idc = p_peek[4] & 0x60; - if( memcmp( p_peek, "\x00\x00\x00\x01", 4 ) || - (p_peek[4] & 0x80) || /* reserved 0 */ - i_nal_type == 0 || i_nal_type > 12 || - ( !i_ref_idc && (i_nal_type < 6 || i_nal_type == 7 || i_nal_type == 8) ) || - ( i_ref_idc && (i_nal_type == 6 || i_nal_type >= 9) ) - ) + if( memcmp( p_peek, "\x00\x00\x00\x01", 4 ) || !pf_probe( p_peek, 5 ) ) { if( !p_demux->b_force ) { - msg_Warn( p_demux, "h264 module discarded (no startcode)" ); + msg_Warn( p_demux, "%s module discarded (no startcode)", psz_module ); return VLC_EGENERIC; } - msg_Err( p_demux, "this doesn't look like a H264 ES stream, " - "continuing anyway" ); + msg_Err( p_demux, "this doesn't look like a %s ES stream, " + "continuing anyway", psz_module ); } p_demux->pf_demux = Demux; @@ -111,7 +146,15 @@ static int Open( vlc_object_t * p_this ) p_sys->p_es = NULL; p_sys->frame_rate_num = 0; p_sys->frame_rate_den = 0; - float f_fps = var_CreateGetFloat( p_demux, "h264-fps" ); + + float f_fps = 0; + char *psz_fpsvar; + if( asprintf( &psz_fpsvar, "%s-fps", psz_module ) ) + { + f_fps = var_CreateGetFloat( p_demux, psz_fpsvar ); + free( psz_fpsvar ); + } + if( f_fps ) { if ( f_fps < 0.001f ) f_fps = 0.001f; @@ -124,8 +167,8 @@ static int Open( vlc_object_t * p_this ) date_Set( &p_sys->dts, VLC_TS_0 ); /* Load the mpegvideo packetizer */ - es_format_Init( &fmt, VIDEO_ES, VLC_CODEC_H264 ); - p_sys->p_packetizer = demux_PacketizerNew( p_demux, &fmt, "h264" ); + es_format_Init( &fmt, VIDEO_ES, i_codec ); + p_sys->p_packetizer = demux_PacketizerNew( p_demux, &fmt, psz_module ); if( !p_sys->p_packetizer ) { free( p_sys ); @@ -135,6 +178,19 @@ static int Open( vlc_object_t * p_this ) return VLC_SUCCESS; } +/***************************************************************************** + * Open: initializes demux structures + *****************************************************************************/ +static int OpenH264( vlc_object_t * p_this ) +{ + return GenericOpen( (demux_t*)p_this, "h264", VLC_CODEC_H264, ProbeH264 ); +} + +static int OpenHEVC( vlc_object_t * p_this ) +{ + return GenericOpen( (demux_t*)p_this, "hevc", VLC_CODEC_HEVC, ProbeHEVC ); +} + /***************************************************************************** * Close: frees unused data *****************************************************************************/ @@ -157,7 +213,7 @@ static int Demux( demux_t *p_demux) demux_sys_t *p_sys = p_demux->p_sys; block_t *p_block_in, *p_block_out; - if( ( p_block_in = stream_Block( p_demux->s, H264_PACKET_SIZE ) ) == NULL ) + if( ( p_block_in = stream_Block( p_demux->s, H26X_PACKET_SIZE ) ) == NULL ) { return 0; } diff --git a/modules/demux/mpeg/hevc.c b/modules/demux/mpeg/hevc.c deleted file mode 100644 index 695ad388542f949e488e7d68a292e03f33b720e5..0000000000000000000000000000000000000000 --- a/modules/demux/mpeg/hevc.c +++ /dev/null @@ -1,231 +0,0 @@ -/***************************************************************************** - * hevc.c : HEVC Video demuxer - ***************************************************************************** - * Copyright (C) 2014 VLC authors and VideoLAN - * $Id$ - * - * Authors: Denis Charmet <typx@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. - *****************************************************************************/ - -/***************************************************************************** - * Preamble - *****************************************************************************/ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <vlc_common.h> -#include <vlc_plugin.h> -#include <vlc_demux.h> -#include <vlc_codec.h> -#include <vlc_mtime.h> - -/***************************************************************************** - * Module descriptor - *****************************************************************************/ -static int Open ( vlc_object_t * ); -static void Close( vlc_object_t * ); - -#define FPS_TEXT N_("Frames per Second") -#define FPS_LONGTEXT N_("Desired frame rate for the stream.") - - -vlc_module_begin () - set_shortname( "HEVC") - set_category( CAT_INPUT ) - set_subcategory( SUBCAT_INPUT_DEMUX ) - set_description( N_("HEVC/H.265 video demuxer" ) ) - set_capability( "demux", 0 ) - add_float( "hevc-force-fps", 0.0, FPS_TEXT, FPS_LONGTEXT, true ) - set_callbacks( Open, Close ) - add_shortcut( "hevc" ) -vlc_module_end () - -/***************************************************************************** - * Local prototypes - *****************************************************************************/ - -static int Demux( demux_t * ); -static int Control( demux_t *, int, va_list ); - -struct demux_sys_t -{ - es_out_id_t *p_es; - - date_t dts; - unsigned frame_rate_num; - unsigned frame_rate_den; - decoder_t *p_packetizer; -}; -#define HEVC_BLOCK_SIZE 2048 - -/***************************************************************************** - * Open: initializes demux structures - *****************************************************************************/ -static int Open( vlc_object_t * p_this ) -{ - demux_t *p_demux = (demux_t*)p_this; - demux_sys_t *p_sys; - const uint8_t *p_peek; - es_format_t fmt; - - if( stream_Peek( p_demux->s, &p_peek, 5 ) < 5 ) return VLC_EGENERIC; - - if( p_peek[0] != 0x00 || p_peek[1] != 0x00 || - p_peek[2] != 0x00 || p_peek[3] != 0x01 || - (p_peek[4]&0xFE) != 0x40 ) /* VPS & forbidden zero bit*/ - { - if( !p_demux->b_force ) - { - msg_Warn( p_demux, "hevc module discarded (no startcode)" ); - return VLC_EGENERIC; - } - - msg_Err( p_demux, "this doesn't look like a HEVC ES stream, " - "continuing anyway" ); - } - - p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); - - if( !p_demux->p_sys ) - return VLC_ENOMEM; - - p_sys->p_es = NULL; - p_sys->frame_rate_num = p_sys->frame_rate_den = 0; - float f_force_fps = var_CreateGetFloat( p_demux, "hevc-force-fps" ); - if( f_force_fps != 0.0f ) - { - if ( f_force_fps < 0.001f ) f_force_fps = 0.001f; - p_sys->frame_rate_den = 1000; - p_sys->frame_rate_num = 1000 * f_force_fps; - date_Init( &p_sys->dts, p_sys->frame_rate_num, p_sys->frame_rate_den ); - } - else - date_Init( &p_sys->dts, 25000, 1000 ); /* Will be overwritten */ - date_Set( &p_sys->dts, VLC_TS_0 ); - - /* Load the hevc packetizer */ - es_format_Init( &fmt, VIDEO_ES, VLC_CODEC_HEVC ); - p_sys->p_packetizer = demux_PacketizerNew( p_demux, &fmt, "hevc" ); - if( !p_sys->p_packetizer ) - { - free( p_sys ); - return VLC_EGENERIC; - } - - p_sys->p_es = NULL; - p_demux->pf_demux = Demux; - p_demux->pf_control= Control; - - return VLC_SUCCESS; -} - -/***************************************************************************** - * Close: frees unused data - *****************************************************************************/ -static void Close( vlc_object_t * p_this ) -{ - demux_t *p_demux = (demux_t*)p_this; - demux_sys_t *p_sys = p_demux->p_sys; - - if( p_sys->p_es ) - es_out_Del( p_demux->out, p_sys->p_es ); - - demux_PacketizerDestroy( p_sys->p_packetizer ); - - free( p_sys ); -} - -/***************************************************************************** - * Demux: reads and demuxes data packets - ***************************************************************************** - * Returns -1 in case of error, 0 in case of EOF, 1 otherwise - *****************************************************************************/ -static int Demux( demux_t *p_demux) -{ - demux_sys_t *p_sys = p_demux->p_sys; - block_t *p_block_in, *p_block_out; - - if( ( p_block_in = stream_Block( p_demux->s, HEVC_BLOCK_SIZE ) ) == NULL ) - { - return 0; - } - - while( (p_block_out = p_sys->p_packetizer->pf_packetize( p_sys->p_packetizer, &p_block_in )) ) - { - while( p_block_out ) - { - block_t *p_next = p_block_out->p_next; - p_block_out->p_next = NULL; - - /* As we'll receive the pts of the head of the packetizer helper blockstream - * the dts/pts will always be late until next frame. */ - p_block_in->i_dts = date_Get( &p_sys->dts ); - p_block_in->i_pts = VLC_TS_INVALID; - - if( p_sys->p_es == NULL ) - { - p_sys->p_packetizer->fmt_out.b_packetized = true; - p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_out); - if( !p_sys->p_es ) - return VLC_DEMUXER_EOF; - } - - bool frame = p_block_out->i_flags & BLOCK_FLAG_TYPE_MASK; - es_out_Send( p_demux->out, p_sys->p_es, p_block_out ); - if( frame ) - { - if( !p_sys->frame_rate_den ) - { - /* Use packetizer's one */ - if( p_sys->p_packetizer->fmt_out.video.i_frame_rate_base ) - { - p_sys->frame_rate_num = p_sys->p_packetizer->fmt_out.video.i_frame_rate; - p_sys->frame_rate_den = p_sys->p_packetizer->fmt_out.video.i_frame_rate_base; - } - else - { - p_sys->frame_rate_num = 25000; - p_sys->frame_rate_den = 1000; - } - date_Init( &p_sys->dts, p_sys->frame_rate_num, p_sys->frame_rate_den ); - date_Set( &p_sys->dts, VLC_TS_0 ); - msg_Dbg( p_demux, "using %.2f fps", (double) p_sys->frame_rate_num / p_sys->frame_rate_den ); - } - - es_out_Control( p_demux->out, ES_OUT_SET_PCR, date_Get( &p_sys->dts ) ); - date_Increment( &p_sys->dts, 1 ); - } - - p_block_out = p_next; - - } - } - return 1; -} - -/***************************************************************************** - * Control: - *****************************************************************************/ -static int Control( demux_t *p_demux, int i_query, va_list args ) -{ - return demux_vaControlHelper( p_demux->s, - 0, -1, - 0, 1, i_query, args ); -} - diff --git a/po/POTFILES.in b/po/POTFILES.in index 021f6f2437fc33c597f54aa36ebf177eb863baa6..b18585e9c58f28047bbbc414e6a84e68b6132a21 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -492,8 +492,7 @@ modules/demux/mp4/libmp4.h modules/demux/mp4/mp4.c modules/demux/mpc.c modules/demux/mpeg/es.c -modules/demux/mpeg/h264.c -modules/demux/mpeg/hevc.c +modules/demux/mpeg/h26x.c modules/demux/mpeg/mpgv.c modules/demux/mpeg/ps.c modules/demux/mpeg/ps.h