/*****************************************************************************
* demux.c: demuxer using ffmpeg (libavformat).
*****************************************************************************
- * Copyright (C) 2004-2007 the VideoLAN team
+ * Copyright (C) 2004-2009 the VideoLAN team
* $Id$
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
#include <vlc_meta.h>
#include <vlc_input.h>
#include <vlc_charset.h>
+#include <vlc_avcodec.h>
/* ffmpeg header */
#if defined(HAVE_LIBAVFORMAT_AVFORMAT_H)
#include "../../codec/avcodec/avcodec.h"
#include "avformat.h"
+#include "../vobsub.h"
//#define AVFORMAT_DEBUG 1
return VLC_EGENERIC;
}
+ vlc_avcodec_lock(); /* avformat calls avcodec behind our back!!! */
if( av_find_stream_info( p_sys->ic ) < 0 )
{
+ vlc_avcodec_unlock();
msg_Err( p_demux, "av_find_stream_info failed" );
if( !b_avfmt_nofile ) p_sys->fmt->flags ^= AVFMT_NOFILE;
CloseDemux( p_this );
return VLC_EGENERIC;
}
+ vlc_avcodec_unlock();
if( !b_avfmt_nofile ) p_sys->fmt->flags ^= AVFMT_NOFILE;
for( i = 0; i < p_sys->ic->nb_streams; i++ )
case CODEC_TYPE_SUBTITLE:
es_format_Init( &fmt, SPU_ES, fcc );
+ if( strncmp( p_sys->ic->iformat->name, "matroska", 8 ) == 0 &&
+ cc->codec_id == CODEC_ID_DVD_SUBTITLE &&
+ cc->extradata != NULL &&
+ cc->extradata_size > 0 )
+ {
+ char *psz_start;
+ char *psz_buf = malloc( cc->extradata_size + 1);
+ if( psz_buf != NULL )
+ {
+ memcpy( psz_buf, cc->extradata , cc->extradata_size );
+ psz_buf[cc->extradata_size] = '\0';
+
+ psz_start = strstr( psz_buf, "size:" );
+ if( psz_start &&
+ vobsub_size_parse( psz_start,
+ &fmt.subs.spu.i_original_frame_width,
+ &fmt.subs.spu.i_original_frame_height ) == VLC_SUCCESS )
+ {
+ msg_Dbg( p_demux, "original frame size: %dx%d",
+ fmt.subs.spu.i_original_frame_width,
+ fmt.subs.spu.i_original_frame_height );
+ }
+ else
+ {
+ msg_Warn( p_demux, "reading original frame size failed" );
+ }
+
+ psz_start = strstr( psz_buf, "palette:" );
+ if( psz_start &&
+ vobsub_palette_parse( psz_start, &fmt.subs.spu.palette[1] ) == VLC_SUCCESS )
+ {
+ fmt.subs.spu.palette[0] = 0xBeef;
+ msg_Dbg( p_demux, "vobsub palette read" );
+ }
+ else
+ {
+ msg_Warn( p_demux, "reading original palette failed" );
+ }
+ free( psz_buf );
+ }
+ }
+
psz_type = "subtitle";
break;
msg_Warn( p_demux, "unsupported track type in ffmpeg demux" );
break;
}
- fmt.psz_language = strdup( p_sys->ic->streams[i]->language );
+ fmt.psz_language = p_sys->ic->streams[i]->language;
#ifdef HAVE_FFMPEG_CODEC_ATTACHMENT
if( cc->codec_type != CODEC_TYPE_ATTACHMENT )
av_free_packet( &pkt );
return 1;
}
+ const AVStream *p_stream = p_sys->ic->streams[pkt.stream_index];
+
if( ( p_frame = block_New( p_demux, pkt.size ) ) == NULL )
{
return 0;
p_frame->i_dts = ( pkt.dts == (int64_t)AV_NOPTS_VALUE ) ?
0 : (pkt.dts) * 1000000 *
- p_sys->ic->streams[pkt.stream_index]->time_base.num /
- p_sys->ic->streams[pkt.stream_index]->time_base.den - i_start_time;
+ p_stream->time_base.num /
+ p_stream->time_base.den - i_start_time;
p_frame->i_pts = ( pkt.pts == (int64_t)AV_NOPTS_VALUE ) ?
0 : (pkt.pts) * 1000000 *
- p_sys->ic->streams[pkt.stream_index]->time_base.num /
- p_sys->ic->streams[pkt.stream_index]->time_base.den - i_start_time;
+ p_stream->time_base.num /
+ p_stream->time_base.den - i_start_time;
if( pkt.duration > 0 )
p_frame->i_length = pkt.duration * 1000000 *
- p_sys->ic->streams[pkt.stream_index]->time_base.num /
- p_sys->ic->streams[pkt.stream_index]->time_base.den - i_start_time;
+ p_stream->time_base.num /
+ p_stream->time_base.den - i_start_time;
+ if( pkt.dts != AV_NOPTS_VALUE && pkt.dts == pkt.pts &&
+ p_stream->codec->codec_type == CODEC_TYPE_VIDEO )
+ {
+ /* Add here notoriously bugged file formats/samples regarding PTS */
+ if( !strcmp( p_sys->fmt->name, "flv" ) )
+ p_frame->i_pts = 0;
+ }
#ifdef AVFORMAT_DEBUG
msg_Dbg( p_demux, "tk[%d] dts=%"PRId64" pts=%"PRId64,
pkt.stream_index, p_frame->i_dts, p_frame->i_pts );
case DEMUX_SET_POSITION:
f = (double) va_arg( args, double );
- i64 = stream_Tell( p_demux->s );
if( p_sys->i_pcr > 0 )
{
i64 = p_sys->ic->duration * f;
(av_seek_frame( p_sys->ic, -1, i64, 0 ) < 0) )
{
int64_t i_size = stream_Size( p_demux->s );
+ i64 = (i_size * f);
msg_Warn( p_demux, "DEMUX_SET_BYTE_POSITION: %"PRId64, i64 );
- if( av_seek_frame( p_sys->ic, -1, (i_size * f), AVSEEK_FLAG_BYTE ) < 0 )
+ if( av_seek_frame( p_sys->ic, -1, i64, AVSEEK_FLAG_BYTE ) < 0 )
return VLC_EGENERIC;
}
- UpdateSeekPoint( p_demux, i64 );
+ else
+ {
+ UpdateSeekPoint( p_demux, i64 );
+ }
p_sys->i_pcr = -1; /* Invalidate time display */
}
return VLC_SUCCESS;
{
URLContext *p_url = opaque;
demux_t *p_demux = p_url->priv_data;
- int64_t i_absolute = (int64_t)offset;
+ int64_t i_absolute;
int64_t i_size = stream_Size( p_demux->s );
#ifdef AVFORMAT_DEBUG