X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Favformat%2Fdemux.c;h=757f353d22d10ade42cd4188bff2b20447927d74;hb=46576f85796c8fd8a06df1d39102fed7b6f9a82c;hp=4787ef7f28d89fdd41d81b5452c1be04babe5347;hpb=6883dcd3ce6db1ffc874c0bf33c788106819a8c8;p=vlc diff --git a/modules/demux/avformat/demux.c b/modules/demux/avformat/demux.c index 4787ef7f28..757f353d22 100644 --- a/modules/demux/avformat/demux.c +++ b/modules/demux/avformat/demux.c @@ -84,6 +84,8 @@ struct demux_sys_t int64_t i_pcr_inc; int i_pcr_tk; + unsigned i_ssa_order; + int i_attachments; input_attachment_t **attachments; @@ -100,6 +102,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args ); static int IORead( void *opaque, uint8_t *buf, int buf_size ); static int64_t IOSeek( void *opaque, int64_t offset, int whence ); +static block_t *BuildSsaFrame( const AVPacket *p_pkt, unsigned i_order ); static void UpdateSeekPoint( demux_t *p_demux, int64_t i_time ); /***************************************************************************** @@ -113,6 +116,7 @@ int OpenDemux( vlc_object_t *p_this ) AVInputFormat *fmt; unsigned int i; int64_t i_start_time = -1; + bool b_can_seek; /* Init Probe data */ pd.filename = p_demux->psz_path; @@ -176,6 +180,7 @@ int OpenDemux( vlc_object_t *p_this ) p_sys->tk = NULL; p_sys->i_pcr_tk = -1; p_sys->i_pcr = -1; + p_sys->i_ssa_order = 0; TAB_INIT( p_sys->i_attachments, p_sys->attachments); p_sys->p_title = NULL; @@ -196,6 +201,18 @@ int OpenDemux( vlc_object_t *p_this ) init_put_byte( &p_sys->io, p_sys->io_buffer, p_sys->io_buffer_size, 0, &p_sys->url, IORead, NULL, IOSeek ); + stream_Control( p_demux->s, STREAM_CAN_SEEK, &b_can_seek ); + if( !b_can_seek ) + { + /* Tell avformat that input is stream, so it doesn't get stuck + when trying av_find_stream_info() trying to seek all the wrong places + init_put_byte defaults io.is_streamed=0, so thats why we set them after it + */ + p_sys->url.is_streamed = 1; + p_sys->io.is_streamed = 1; + } + + /* Open it */ if( av_open_input_stream( &p_sys->ic, &p_sys->io, p_demux->psz_path, p_sys->fmt, NULL ) ) @@ -208,7 +225,6 @@ int OpenDemux( vlc_object_t *p_this ) vlc_avcodec_lock(); /* avformat calls avcodec behind our back!!! */ if( av_find_stream_info( p_sys->ic ) < 0 ) { - vlc_avcodec_unlock(); msg_Warn( p_demux, "av_find_stream_info failed" ); } vlc_avcodec_unlock(); @@ -256,6 +272,10 @@ int OpenDemux( vlc_object_t *p_this ) else fmt.i_codec = fmt.video.i_chroma; } + /* We need this for the h264 packetizer */ + else if( cc->codec_id == CODEC_ID_H264 && ( !strcmp( p_sys->fmt->name, "flv" ) || + !strcmp( p_sys->fmt->name, "matroska" ) || !strcmp( p_sys->fmt->name, "mp4" ) ) ) + fmt.i_original_fourcc = VLC_FOURCC( 'a', 'v', 'c', '1' ); fmt.video.i_width = cc->width; fmt.video.i_height = cc->height; @@ -265,6 +285,8 @@ int OpenDemux( vlc_object_t *p_this ) *fmt.video.p_palette = *(video_palette_t *)cc->palctrl; } psz_type = "video"; + fmt.video.i_frame_rate = cc->time_base.den; + fmt.video.i_frame_rate_base = cc->time_base.num; break; case CODEC_TYPE_SUBTITLE: @@ -494,13 +516,30 @@ static int Demux( demux_t *p_demux ) return 1; } const AVStream *p_stream = p_sys->ic->streams[pkt.stream_index]; - - if( ( p_frame = block_New( p_demux, pkt.size ) ) == NULL ) + if( p_stream->time_base.den <= 0 ) { - return 0; + msg_Warn( p_demux, "Invalid time base for the stream %d", pkt.stream_index ); + av_free_packet( &pkt ); + return 1; + } + if( p_stream->codec->codec_id == CODEC_ID_SSA ) + { + p_frame = BuildSsaFrame( &pkt, p_sys->i_ssa_order++ ); + if( !p_frame ) + { + av_free_packet( &pkt ); + return 1; + } + } + else + { + if( ( p_frame = block_New( p_demux, pkt.size ) ) == NULL ) + { + av_free_packet( &pkt ); + return 0; + } + memcpy( p_frame->p_buffer, pkt.data, pkt.size ); } - - memcpy( p_frame->p_buffer, pkt.data, pkt.size ); if( pkt.flags & PKT_FLAG_KEY ) p_frame->i_flags |= BLOCK_FLAG_TYPE_I; @@ -516,10 +555,10 @@ static int Demux( demux_t *p_demux ) VLC_TS_INVALID : (pkt.pts) * 1000000 * p_stream->time_base.num / p_stream->time_base.den - i_start_time + VLC_TS_0; - if( pkt.duration > 0 ) + if( pkt.duration > 0 && p_frame->i_length <= 0 ) p_frame->i_length = pkt.duration * 1000000 * p_stream->time_base.num / - p_stream->time_base.den - i_start_time; + p_stream->time_base.den; if( pkt.dts != AV_NOPTS_VALUE && pkt.dts == pkt.pts && p_stream->codec->codec_type == CODEC_TYPE_VIDEO ) @@ -571,6 +610,40 @@ static void UpdateSeekPoint( demux_t *p_demux, int64_t i_time ) } } +static block_t *BuildSsaFrame( const AVPacket *p_pkt, unsigned i_order ) +{ + if( p_pkt->size <= 0 ) + return NULL; + + char buffer[256]; + const size_t i_buffer_size = __MIN( sizeof(buffer) - 1, p_pkt->size ); + memcpy( buffer, p_pkt->data, i_buffer_size ); + buffer[i_buffer_size] = '\0'; + + /* */ + int i_layer; + int h0, m0, s0, c0; + int h1, m1, s1, c1; + int i_position = 0; + if( sscanf( buffer, "Dialogue: %d,%d:%d:%d.%d,%d:%d:%d.%d,%n", &i_layer, + &h0, &m0, &s0, &c0, &h1, &m1, &s1, &c1, &i_position ) < 9 ) + return NULL; + if( i_position <= 0 || i_position >= i_buffer_size ) + return NULL; + + char *p; + if( asprintf( &p, "%u,%d,%.*s", i_order, i_layer, p_pkt->size - i_position, p_pkt->data + i_position ) < 0 ) + return NULL; + + block_t *p_frame = block_heap_Alloc( p, p, strlen(p) + 1 ); + if( p_frame ) + p_frame->i_length = CLOCK_FREQ * ((h1 - h1) * 3600 + + (m1-m0) * 60 + + (s1-s0) * 1) + + CLOCK_FREQ * (c1-c0) / 100; + return p_frame; +} + /***************************************************************************** * Control: *****************************************************************************/ @@ -631,10 +704,9 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) case DEMUX_GET_LENGTH: pi64 = (int64_t*)va_arg( args, int64_t * ); if( p_sys->ic->duration != (int64_t)AV_NOPTS_VALUE ) - { - *pi64 = p_sys->ic->duration; - } - else *pi64 = 0; + *pi64 = p_sys->ic->duration * 1000000 / AV_TIME_BASE; + else + *pi64 = 0; return VLC_SUCCESS; case DEMUX_GET_TIME: