2001-07-22 14:18:56 +00:00
/*
2008-01-16 22:14:26 +00:00
* various utility functions for use within FFmpeg
2002-05-25 22:34:32 +00:00
* Copyright (c) 2000, 2001, 2002 Fabrice Bellard
2001-07-22 14:18:56 +00:00
*
2006-10-07 15:30:46 +00:00
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
2002-05-25 22:34:32 +00:00
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
2006-10-07 15:30:46 +00:00
* version 2.1 of the License, or (at your option) any later version.
2001-07-22 14:18:56 +00:00
*
2006-10-07 15:30:46 +00:00
* FFmpeg is distributed in the hope that it will be useful,
2001-07-22 14:18:56 +00:00
* but WITHOUT ANY WARRANTY; without even the implied warranty of
2002-05-25 22:34:32 +00:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
2001-07-22 14:18:56 +00:00
*
2002-05-25 22:34:32 +00:00
* You should have received a copy of the GNU Lesser General Public
2006-10-07 15:30:46 +00:00
* License along with FFmpeg; if not, write to the Free Software
2006-01-12 22:43:26 +00:00
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2001-07-22 14:18:56 +00:00
*/
2011-03-15 13:11:57 +01:00
2013-11-23 21:32:55 +01:00
#include <stdint.h>
2014-01-16 01:53:03 +01:00
#include "config.h"
2012-01-05 10:14:07 +01:00
#include "libavutil/avassert.h"
2008-05-09 11:56:36 +00:00
#include "libavutil/avstring.h"
2021-07-23 04:01:44 +02:00
#include "libavutil/bprint.h"
2014-01-16 01:53:03 +01:00
#include "libavutil/dict.h"
#include "libavutil/internal.h"
2011-06-04 12:58:23 +01:00
#include "libavutil/mathematics.h"
2014-01-16 01:53:03 +01:00
#include "libavutil/opt.h"
2011-11-07 23:32:21 +02:00
#include "libavutil/parseutils.h"
2020-04-21 01:09:19 +02:00
#include "libavutil/pixfmt.h"
2017-12-21 22:54:06 +01:00
#include "libavutil/thread.h"
2012-07-27 16:28:36 +02:00
#include "libavutil/time.h"
2012-05-13 22:22:35 +02:00
#include "libavutil/timestamp.h"
2014-01-16 01:53:03 +01:00
2021-06-11 23:35:33 +02:00
#include "libavcodec/bsf.h"
2014-01-16 01:53:03 +01:00
#include "libavcodec/bytestream.h"
#include "libavcodec/internal.h"
2020-08-17 12:03:50 -03:00
#include "libavcodec/packet_internal.h"
2014-01-26 23:35:38 +01:00
#include "libavcodec/raw.h"
2014-01-16 01:53:03 +01:00
#include "avformat.h"
#include "avio_internal.h"
#include "id3v2.h"
#include "internal.h"
2010-03-05 22:31:45 +00:00
#if CONFIG_NETWORK
#include "network.h"
#endif
2014-01-16 01:53:03 +01:00
#include "url.h"
2004-01-13 22:02:49 +00:00
2014-12-19 18:04:40 +01:00
#include "libavutil/ffversion.h"
const char av_format_ffversion [] = "FFmpeg version " FFMPEG_VERSION ;
2017-12-21 22:54:06 +01:00
static AVMutex avformat_mutex = AV_MUTEX_INITIALIZER ;
2005-06-28 12:55:08 +00:00
/**
2010-04-20 14:45:34 +00:00
* @file
2008-01-16 22:14:26 +00:00
* various utility functions for use within FFmpeg
2005-06-28 12:55:08 +00:00
*/
2008-08-08 18:40:50 +00:00
unsigned avformat_version ( void )
{
2011-12-22 03:06:06 +01:00
av_assert0 ( LIBAVFORMAT_VERSION_MICRO >= 100 );
2008-08-08 18:40:50 +00:00
return LIBAVFORMAT_VERSION_INT ;
}
2010-01-03 14:31:25 +00:00
const char * avformat_configuration ( void )
2009-11-18 17:15:17 +00:00
{
2011-03-17 17:01:10 +01:00
return FFMPEG_CONFIGURATION ;
2009-11-18 17:15:17 +00:00
}
2010-01-03 14:31:25 +00:00
const char * avformat_license ( void )
2009-11-18 17:15:17 +00:00
{
#define LICENSE_PREFIX "libavformat license: "
2020-01-06 16:16:18 +01:00
return & LICENSE_PREFIX FFMPEG_LICENSE [ sizeof ( LICENSE_PREFIX ) - 1 ];
2009-11-18 17:15:17 +00:00
}
2017-12-21 22:54:06 +01:00
int ff_lock_avformat ( void )
{
return ff_mutex_lock ( & avformat_mutex ) ? - 1 : 0 ;
}
int ff_unlock_avformat ( void )
{
return ff_mutex_unlock ( & avformat_mutex ) ? - 1 : 0 ;
}
2012-04-03 23:34:53 +02:00
#define RELATIVE_TS_BASE (INT64_MAX - (1LL<<48))
2012-03-07 22:13:39 +01:00
static int is_relative ( int64_t ts ) {
2012-04-03 23:34:53 +02:00
return ts > ( RELATIVE_TS_BASE - ( 1LL << 48 ));
2012-03-07 22:13:39 +01:00
}
2012-12-02 19:27:21 +01:00
/**
* Wrap a given time stamp, if there is an indication for an overflow
*
* @param st stream
* @param timestamp the time stamp to wrap
* @return resulting time stamp
*/
2016-06-27 11:25:23 +02:00
static int64_t wrap_timestamp ( const AVStream * st , int64_t timestamp )
2012-12-02 19:27:21 +01:00
{
2020-10-23 10:53:18 +02:00
if ( st -> internal -> pts_wrap_behavior != AV_PTS_WRAP_IGNORE && st -> pts_wrap_bits < 64 &&
2020-10-09 09:22:36 +02:00
st -> internal -> pts_wrap_reference != AV_NOPTS_VALUE && timestamp != AV_NOPTS_VALUE ) {
if ( st -> internal -> pts_wrap_behavior == AV_PTS_WRAP_ADD_OFFSET &&
timestamp < st -> internal -> pts_wrap_reference )
2014-01-26 23:35:38 +01:00
return timestamp + ( 1ULL << st -> pts_wrap_bits );
2020-10-09 09:22:36 +02:00
else if ( st -> internal -> pts_wrap_behavior == AV_PTS_WRAP_SUB_OFFSET &&
timestamp >= st -> internal -> pts_wrap_reference )
2014-01-26 23:35:38 +01:00
return timestamp - ( 1ULL << st -> pts_wrap_bits );
2012-12-02 19:27:21 +01:00
}
return timestamp ;
}
2014-05-19 20:16:01 +02:00
int64_t av_stream_get_end_pts ( const AVStream * st )
{
2017-11-05 14:59:47 -03:00
if ( st -> internal -> priv_pts ) {
return st -> internal -> priv_pts -> val ;
2015-08-17 16:30:16 +02:00
} else
return AV_NOPTS_VALUE ;
2014-05-19 20:16:01 +02:00
}
2014-07-14 21:03:43 +02:00
struct AVCodecParserContext * av_stream_get_parser ( const AVStream * st )
{
2021-05-01 23:28:18 -03:00
return st -> internal -> parser ;
}
void avpriv_stream_set_need_parsing ( AVStream * st , enum AVStreamParseType type )
{
st -> internal -> need_parsing = type ;
2014-07-14 21:03:43 +02:00
}
2014-04-13 19:20:17 +02:00
void av_format_inject_global_side_data ( AVFormatContext * s )
{
int i ;
s -> internal -> inject_global_side_data = 1 ;
for ( i = 0 ; i < s -> nb_streams ; i ++ ) {
AVStream * st = s -> streams [ i ];
2020-10-09 09:22:36 +02:00
st -> internal -> inject_global_side_data = 1 ;
2014-04-13 19:20:17 +02:00
}
}
2016-06-27 11:25:23 +02:00
int ff_copy_whiteblacklists ( AVFormatContext * dst , const AVFormatContext * src )
2014-10-24 19:23:23 +02:00
{
2016-01-30 02:17:50 +01:00
av_assert0 ( ! dst -> codec_whitelist &&
! dst -> format_whitelist &&
2016-03-03 17:14:26 +00:00
! dst -> protocol_whitelist &&
! dst -> protocol_blacklist );
2014-10-24 19:23:23 +02:00
dst -> codec_whitelist = av_strdup ( src -> codec_whitelist );
dst -> format_whitelist = av_strdup ( src -> format_whitelist );
2016-01-30 02:17:50 +01:00
dst -> protocol_whitelist = av_strdup ( src -> protocol_whitelist );
2016-03-03 17:14:26 +00:00
dst -> protocol_blacklist = av_strdup ( src -> protocol_blacklist );
2014-10-24 19:23:23 +02:00
if ( ( src -> codec_whitelist && ! dst -> codec_whitelist )
2016-01-30 02:17:50 +01:00
|| ( src -> format_whitelist && ! dst -> format_whitelist )
2016-03-03 17:14:26 +00:00
|| ( src -> protocol_whitelist && ! dst -> protocol_whitelist )
|| ( src -> protocol_blacklist && ! dst -> protocol_blacklist )) {
av_log ( dst , AV_LOG_ERROR , "Failed to duplicate black/whitelist \n " );
2014-10-24 19:23:23 +02:00
return AVERROR ( ENOMEM );
}
return 0 ;
}
2016-06-27 11:25:23 +02:00
static const AVCodec * find_decoder ( AVFormatContext * s , const AVStream * st , enum AVCodecID codec_id )
2013-09-28 17:07:47 +02:00
{
2016-04-10 20:58:15 +01:00
switch ( st -> codecpar -> codec_type ) {
2013-09-28 17:52:45 +02:00
case AVMEDIA_TYPE_VIDEO :
2014-01-26 23:35:38 +01:00
if ( s -> video_codec ) return s -> video_codec ;
2013-09-28 17:52:45 +02:00
break ;
case AVMEDIA_TYPE_AUDIO :
2014-01-26 23:35:38 +01:00
if ( s -> audio_codec ) return s -> audio_codec ;
2013-09-28 17:52:45 +02:00
break ;
case AVMEDIA_TYPE_SUBTITLE :
2014-01-26 23:35:38 +01:00
if ( s -> subtitle_codec ) return s -> subtitle_codec ;
2013-09-28 17:52:45 +02:00
break ;
}
2013-09-28 17:07:47 +02:00
return avcodec_find_decoder ( codec_id );
}
2016-09-21 19:00:46 +02:00
static const AVCodec * find_probe_decoder ( AVFormatContext * s , const AVStream * st , enum AVCodecID codec_id )
{
2016-09-22 12:10:15 +02:00
const AVCodec * codec ;
2016-09-21 19:00:46 +02:00
#if CONFIG_H264_DECODER
/* Other parts of the code assume this decoder to be used for h264,
* so force it if possible. */
if ( codec_id == AV_CODEC_ID_H264 )
return avcodec_find_decoder_by_name ( "h264" );
#endif
2016-09-22 12:10:15 +02:00
codec = find_decoder ( s , st , codec_id );
if ( ! codec )
return NULL ;
if ( codec -> capabilities & AV_CODEC_CAP_AVOID_PROBING ) {
const AVCodec * probe_codec = NULL ;
2020-04-14 12:21:52 +01:00
void * iter = NULL ;
while (( probe_codec = av_codec_iterate ( & iter ))) {
2020-06-03 07:15:28 -04:00
if ( probe_codec -> id == codec -> id &&
2016-09-22 12:10:15 +02:00
av_codec_is_decoder ( probe_codec ) &&
! ( probe_codec -> capabilities & ( AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_EXPERIMENTAL ))) {
return probe_codec ;
}
}
}
return codec ;
2016-09-21 19:00:46 +02:00
}
2013-02-19 17:20:35 +01:00
/* an arbitrarily chosen "sane" max packet size -- 50M */
#define SANE_CHUNK_SIZE (50000000)
2014-01-16 01:53:03 +01:00
/* Read the data in sane-sized chunks and append to pkt.
* Return the number of bytes read or an error. */
2013-02-19 17:20:35 +01:00
static int append_packet_chunked ( AVIOContext * s , AVPacket * pkt , int size )
2011-12-19 11:46:34 +01:00
{
2013-02-19 17:20:35 +01:00
int orig_size = pkt -> size ;
2013-03-16 17:03:41 +01:00
int ret ;
2011-12-16 05:54:03 +01:00
2013-02-19 17:20:35 +01:00
do {
int prev_size = pkt -> size ;
int read_size ;
2005-05-26 20:17:12 +00:00
2014-01-16 01:53:03 +01:00
/* When the caller requests a lot of data, limit it to the amount
* left in file or SANE_CHUNK_SIZE when it is not known. */
2013-03-16 15:12:21 +01:00
read_size = size ;
if ( read_size > SANE_CHUNK_SIZE / 10 ) {
read_size = ffio_limit ( s , read_size );
// If filesize/maxsize is unknown, limit to SANE_CHUNK_SIZE
2021-08-04 16:52:07 +02:00
if ( ffiocontext ( s ) -> maxsize < 0 )
2013-03-16 15:12:21 +01:00
read_size = FFMIN ( read_size , SANE_CHUNK_SIZE );
}
2005-05-26 20:17:12 +00:00
2013-02-19 17:20:35 +01:00
ret = av_grow_packet ( pkt , read_size );
if ( ret < 0 )
break ;
2005-05-26 20:17:12 +00:00
2013-02-19 17:20:35 +01:00
ret = avio_read ( s , pkt -> data + prev_size , read_size );
if ( ret != read_size ) {
av_shrink_packet ( pkt , prev_size + FFMAX ( ret , 0 ));
break ;
}
size -= read_size ;
} while ( size > 0 );
2013-03-16 15:12:21 +01:00
if ( size > 0 )
2012-04-30 22:58:27 +02:00
pkt -> flags |= AV_PKT_FLAG_CORRUPT ;
2005-05-26 20:17:12 +00:00
2013-02-19 17:20:35 +01:00
if ( ! pkt -> size )
2015-10-23 11:11:31 +02:00
av_packet_unref ( pkt );
2013-02-19 17:20:35 +01:00
return pkt -> size > orig_size ? pkt -> size - orig_size : ret ;
}
2001-07-22 14:18:56 +00:00
2011-02-20 11:04:12 +01:00
int av_get_packet ( AVIOContext * s , AVPacket * pkt , int size )
2005-05-26 20:17:12 +00:00
{
2021-01-31 13:05:49 -03:00
#if FF_API_INIT_PACKET
FF_DISABLE_DEPRECATION_WARNINGS
2013-02-19 17:20:35 +01:00
av_init_packet ( pkt );
pkt -> data = NULL ;
pkt -> size = 0 ;
2021-01-31 13:05:49 -03:00
FF_ENABLE_DEPRECATION_WARNINGS
#else
av_packet_unref ( pkt );
#endif
2013-02-19 17:20:35 +01:00
pkt -> pos = avio_tell ( s );
2005-05-26 20:17:12 +00:00
2013-02-19 17:20:35 +01:00
return append_packet_chunked ( s , pkt , size );
2005-05-26 20:17:12 +00:00
}
2011-02-20 11:04:12 +01:00
int av_append_packet ( AVIOContext * s , AVPacket * pkt , int size )
2010-11-21 10:24:48 +00:00
{
if ( ! pkt -> size )
return av_get_packet ( s , pkt , size );
2013-02-19 17:20:35 +01:00
return append_packet_chunked ( s , pkt , size );
2010-11-21 10:24:48 +00:00
}
2006-09-04 09:57:47 +00:00
int av_filename_number_test ( const char * filename )
2002-05-20 16:28:47 +00:00
{
char buf [ 1024 ];
2014-01-16 01:53:03 +01:00
return filename &&
( av_get_frame_filename ( buf , sizeof ( buf ), filename , 1 ) >= 0 );
2002-05-20 16:28:47 +00:00
}
2014-01-16 01:53:03 +01:00
static int set_codec_from_probe_data ( AVFormatContext * s , AVStream * st ,
2014-01-26 23:35:38 +01:00
AVProbeData * pd )
2008-07-12 13:25:26 +00:00
{
2010-05-22 21:52:02 +00:00
static const struct {
2014-01-16 01:53:03 +01:00
const char * name ;
enum AVCodecID id ;
enum AVMediaType type ;
2010-05-22 21:52:02 +00:00
} fmt_id_type [] = {
2014-01-16 01:53:03 +01:00
{ "aac" , AV_CODEC_ID_AAC , AVMEDIA_TYPE_AUDIO },
{ "ac3" , AV_CODEC_ID_AC3 , AVMEDIA_TYPE_AUDIO },
2017-11-10 22:09:24 +01:00
{ "aptx" , AV_CODEC_ID_APTX , AVMEDIA_TYPE_AUDIO },
2014-01-16 01:53:03 +01:00
{ "dts" , AV_CODEC_ID_DTS , AVMEDIA_TYPE_AUDIO },
2015-01-04 23:21:54 +01:00
{ "dvbsub" , AV_CODEC_ID_DVB_SUBTITLE , AVMEDIA_TYPE_SUBTITLE },
2016-02-16 03:05:10 +01:00
{ "dvbtxt" , AV_CODEC_ID_DVB_TELETEXT , AVMEDIA_TYPE_SUBTITLE },
2014-01-16 01:53:03 +01:00
{ "eac3" , AV_CODEC_ID_EAC3 , AVMEDIA_TYPE_AUDIO },
{ "h264" , AV_CODEC_ID_H264 , AVMEDIA_TYPE_VIDEO },
2014-02-03 11:35:19 +01:00
{ "hevc" , AV_CODEC_ID_HEVC , AVMEDIA_TYPE_VIDEO },
2014-01-26 23:35:38 +01:00
{ "loas" , AV_CODEC_ID_AAC_LATM , AVMEDIA_TYPE_AUDIO },
2014-01-16 01:53:03 +01:00
{ "m4v" , AV_CODEC_ID_MPEG4 , AVMEDIA_TYPE_VIDEO },
2016-10-11 15:36:40 +02:00
{ "mjpeg_2000" , AV_CODEC_ID_JPEG2000 , AVMEDIA_TYPE_VIDEO },
2014-01-16 01:53:03 +01:00
{ "mp3" , AV_CODEC_ID_MP3 , AVMEDIA_TYPE_AUDIO },
2012-08-05 11:11:04 +02:00
{ "mpegvideo" , AV_CODEC_ID_MPEG2VIDEO , AVMEDIA_TYPE_VIDEO },
2015-11-17 10:01:01 -06:00
{ "truehd" , AV_CODEC_ID_TRUEHD , AVMEDIA_TYPE_AUDIO },
2010-05-22 21:52:02 +00:00
{ 0 }
};
2011-03-04 01:12:17 +01:00
int score ;
2019-03-20 18:52:38 +01:00
const AVInputFormat * fmt = av_probe_input_format3 ( pd , 1 , & score );
2008-07-12 13:25:26 +00:00
2016-08-27 01:12:49 +02:00
if ( fmt ) {
2010-05-22 21:52:02 +00:00
int i ;
2014-01-16 01:53:03 +01:00
av_log ( s , AV_LOG_DEBUG ,
"Probe with size=%d, packets=%d detected %s with score=%d \n " ,
2021-05-01 23:13:41 -03:00
pd -> buf_size , s -> max_probe_packets - st -> internal -> probe_packets ,
2014-01-16 01:53:03 +01:00
fmt -> name , score );
2010-05-22 21:52:02 +00:00
for ( i = 0 ; fmt_id_type [ i ]. name ; i ++ ) {
if ( ! strcmp ( fmt -> name , fmt_id_type [ i ]. name )) {
2016-05-04 21:31:18 +02:00
if ( fmt_id_type [ i ]. type != AVMEDIA_TYPE_AUDIO &&
st -> codecpar -> sample_rate )
continue ;
2020-10-09 09:22:36 +02:00
if ( st -> internal -> request_probe > score &&
2016-08-27 01:12:49 +02:00
st -> codecpar -> codec_id != fmt_id_type [ i ]. id )
continue ;
2014-06-18 20:42:52 +02:00
st -> codecpar -> codec_id = fmt_id_type [ i ]. id ;
st -> codecpar -> codec_type = fmt_id_type [ i ]. type ;
2016-04-10 20:58:15 +01:00
st -> internal -> need_context_update = 1 ;
2014-08-07 09:12:34 +02:00
return score ;
2010-05-22 21:52:02 +00:00
}
2008-08-25 15:39:43 +00:00
}
2008-07-12 13:25:26 +00:00
}
2014-08-07 09:12:34 +02:00
return 0 ;
2008-07-12 13:25:26 +00:00
}
2002-05-20 16:28:47 +00:00
/************************************************************/
/* input media file */
2014-01-16 01:53:03 +01:00
/* Open input file and probe the format if necessary. */
static int init_input ( AVFormatContext * s , const char * filename ,
AVDictionary ** options )
2011-05-22 08:37:25 +02:00
{
int ret ;
2014-01-16 01:53:03 +01:00
AVProbeData pd = { filename , NULL , 0 };
2012-10-10 21:41:20 +02:00
int score = AVPROBE_SCORE_RETRY ;
2011-05-22 08:37:25 +02:00
if ( s -> pb ) {
s -> flags |= AVFMT_FLAG_CUSTOM_IO ;
if ( ! s -> iformat )
2014-01-26 23:35:38 +01:00
return av_probe_input_buffer2 ( s -> pb , & s -> iformat , filename ,
2014-01-27 23:09:38 +01:00
s , 0 , s -> format_probesize );
2011-05-22 08:37:25 +02:00
else if ( s -> iformat -> flags & AVFMT_NOFILE )
2011-06-22 18:25:49 +02:00
av_log ( s , AV_LOG_WARNING , "Custom AVIOContext makes no sense and "
"will be ignored with AVFMT_NOFILE format. \n " );
2011-05-22 08:37:25 +02:00
return 0 ;
2001-07-22 14:18:56 +00:00
}
2014-01-16 01:53:03 +01:00
if (( s -> iformat && s -> iformat -> flags & AVFMT_NOFILE ) ||
2012-10-10 21:41:20 +02:00
( ! s -> iformat && ( s -> iformat = av_probe_input_format2 ( & pd , 0 , & score ))))
2013-08-08 22:39:49 +02:00
return score ;
2002-05-20 16:28:47 +00:00
2016-02-10 14:40:32 +00:00
if (( ret = s -> io_open ( s , & s -> pb , filename , AVIO_FLAG_READ | s -> avio_flags , options )) < 0 )
2011-08-22 18:47:24 -07:00
return ret ;
2016-01-30 02:17:50 +01:00
2011-05-22 08:37:25 +02:00
if ( s -> iformat )
return 0 ;
2014-01-26 23:35:38 +01:00
return av_probe_input_buffer2 ( s -> pb , & s -> iformat , filename ,
2014-01-27 23:09:38 +01:00
s , 0 , s -> format_probesize );
2011-05-22 08:37:25 +02:00
}
2013-03-08 17:28:42 +01:00
int avformat_queue_attached_pictures ( AVFormatContext * s )
2012-03-18 17:34:14 +01:00
{
2015-10-23 11:11:32 +02:00
int i , ret ;
2012-03-18 17:34:14 +01:00
for ( i = 0 ; i < s -> nb_streams ; i ++ )
2012-03-18 17:35:49 +01:00
if ( s -> streams [ i ] -> disposition & AV_DISPOSITION_ATTACHED_PIC &&
s -> streams [ i ] -> discard < AVDISCARD_ALL ) {
2015-10-29 14:06:11 +01:00
if ( s -> streams [ i ] -> attached_pic . size <= 0 ) {
2014-05-28 16:31:03 +03:00
av_log ( s , AV_LOG_WARNING ,
"Attached picture on stream %d has invalid size, "
"ignoring \n " , i );
continue ;
}
2012-10-31 08:53:18 +01:00
2020-08-17 12:03:50 -03:00
ret = avpriv_packet_list_put ( & s -> internal -> raw_packet_buffer ,
2018-03-27 19:48:18 -03:00
& s -> internal -> raw_packet_buffer_end ,
& s -> streams [ i ] -> attached_pic ,
2020-08-17 12:03:50 -03:00
av_packet_ref , 0 );
2015-10-23 11:11:32 +02:00
if ( ret < 0 )
return ret ;
2012-03-18 17:34:14 +01:00
}
2012-10-31 08:53:18 +01:00
return 0 ;
2012-03-18 17:34:14 +01:00
}
2021-03-29 08:50:18 +02:00
int ff_add_attached_pic ( AVFormatContext * s , AVStream * st0 , AVIOContext * pb ,
2021-03-29 07:58:56 +02:00
AVBufferRef ** buf , int size )
{
2021-03-29 08:50:18 +02:00
AVStream * st = st0 ;
2021-03-29 07:58:56 +02:00
AVPacket * pkt ;
int ret ;
if ( ! st && ! ( st = avformat_new_stream ( s , NULL )))
return AVERROR ( ENOMEM );
pkt = & st -> attached_pic ;
if ( buf ) {
av_assert1 ( * buf );
av_packet_unref ( pkt );
pkt -> buf = * buf ;
pkt -> data = ( * buf ) -> data ;
pkt -> size = ( * buf ) -> size - AV_INPUT_BUFFER_PADDING_SIZE ;
* buf = NULL ;
} else {
ret = av_get_packet ( pb , pkt , size );
if ( ret < 0 )
2021-03-29 08:50:18 +02:00
goto fail ;
2021-03-29 07:58:56 +02:00
}
st -> disposition |= AV_DISPOSITION_ATTACHED_PIC ;
st -> codecpar -> codec_type = AVMEDIA_TYPE_VIDEO ;
pkt -> stream_index = st -> index ;
pkt -> flags |= AV_PKT_FLAG_KEY ;
return 0 ;
2021-03-29 08:50:18 +02:00
fail :
if ( ! st0 )
ff_free_stream ( s , st );
return ret ;
2021-03-29 07:58:56 +02:00
}
2014-06-18 20:42:52 +02:00
static int update_stream_avctx ( AVFormatContext * s )
{
int i , ret ;
for ( i = 0 ; i < s -> nb_streams ; i ++ ) {
AVStream * st = s -> streams [ i ];
2016-04-10 20:58:15 +01:00
if ( ! st -> internal -> need_context_update )
2014-06-18 20:42:52 +02:00
continue ;
2016-10-17 20:26:51 +02:00
/* close parser, because it depends on the codec */
2021-05-01 23:28:18 -03:00
if ( st -> internal -> parser && st -> internal -> avctx -> codec_id != st -> codecpar -> codec_id ) {
av_parser_close ( st -> internal -> parser );
st -> internal -> parser = NULL ;
2016-10-17 20:26:51 +02:00
}
2016-04-10 20:58:15 +01:00
/* update internal codec context, for the parser */
ret = avcodec_parameters_to_context ( st -> internal -> avctx , st -> codecpar );
2014-06-18 20:42:52 +02:00
if ( ret < 0 )
return ret ;
2016-04-10 20:58:15 +01:00
st -> internal -> need_context_update = 0 ;
2014-06-18 20:42:52 +02:00
}
return 0 ;
}
2016-04-10 20:58:15 +01:00
2014-06-18 20:42:52 +02:00
2014-01-16 01:53:03 +01:00
int avformat_open_input ( AVFormatContext ** ps , const char * filename ,
2021-02-25 03:11:32 +01:00
const AVInputFormat * fmt , AVDictionary ** options )
2011-05-22 08:37:25 +02:00
{
AVFormatContext * s = * ps ;
2021-07-14 16:07:49 -03:00
int ret = 0 ;
2011-05-22 08:37:25 +02:00
AVDictionary * tmp = NULL ;
2012-02-25 09:53:35 +01:00
ID3v2ExtraMeta * id3v2_extra_meta = NULL ;
2011-05-22 08:37:25 +02:00
if ( ! s && ! ( s = avformat_alloc_context ()))
return AVERROR ( ENOMEM );
2014-01-26 23:35:38 +01:00
if ( ! s -> av_class ) {
2012-11-23 18:10:02 +01:00
av_log ( NULL , AV_LOG_ERROR , "Input context has not been properly allocated by avformat_alloc_context() and is not NULL either \n " );
2012-04-18 13:49:07 +02:00
return AVERROR ( EINVAL );
}
2011-05-22 08:37:25 +02:00
if ( fmt )
s -> iformat = fmt ;
if ( options )
av_dict_copy ( & tmp , * options , 0 );
2015-04-20 22:22:31 +02:00
if ( s -> pb ) // must be before any goto fail
s -> flags |= AVFMT_FLAG_CUSTOM_IO ;
2011-05-22 08:37:25 +02:00
if (( ret = av_opt_set_dict ( s , & tmp )) < 0 )
goto fail ;
2017-12-29 01:01:37 +01:00
if ( ! ( s -> url = av_strdup ( filename ? filename : "" ))) {
ret = AVERROR ( ENOMEM );
goto fail ;
}
2011-11-05 12:30:21 +01:00
if (( ret = init_input ( s , filename , & tmp )) < 0 )
2003-10-29 14:20:56 +00:00
goto fail ;
2013-08-08 22:39:49 +02:00
s -> probe_score = ret ;
2014-09-30 23:25:39 +02:00
2016-01-30 02:17:50 +01:00
if ( ! s -> protocol_whitelist && s -> pb && s -> pb -> protocol_whitelist ) {
s -> protocol_whitelist = av_strdup ( s -> pb -> protocol_whitelist );
if ( ! s -> protocol_whitelist ) {
ret = AVERROR ( ENOMEM );
goto fail ;
}
}
2016-03-03 17:14:26 +00:00
if ( ! s -> protocol_blacklist && s -> pb && s -> pb -> protocol_blacklist ) {
s -> protocol_blacklist = av_strdup ( s -> pb -> protocol_blacklist );
if ( ! s -> protocol_blacklist ) {
ret = AVERROR ( ENOMEM );
goto fail ;
}
}
2014-09-30 23:25:39 +02:00
if ( s -> format_whitelist && av_match_list ( s -> iformat -> name , s -> format_whitelist , ',' ) <= 0 ) {
2016-01-24 16:15:24 +01:00
av_log ( s , AV_LOG_ERROR , "Format not on whitelist \' %s \'\n " , s -> format_whitelist );
2014-09-30 23:25:39 +02:00
ret = AVERROR ( EINVAL );
goto fail ;
}
2012-11-20 22:04:14 +01:00
avio_skip ( s -> pb , s -> skip_initial_bytes );
2005-12-17 18:14:38 +00:00
2014-01-16 01:53:03 +01:00
/* Check filename in case an image number is expected. */
2011-05-22 08:37:25 +02:00
if ( s -> iformat -> flags & AVFMT_NEEDNUMBER ) {
2006-09-04 09:57:47 +00:00
if ( ! av_filename_number_test ( filename )) {
2011-05-22 08:37:25 +02:00
ret = AVERROR ( EINVAL );
2003-10-29 14:20:56 +00:00
goto fail ;
2003-01-11 05:02:14 +00:00
}
}
2005-12-17 18:14:38 +00:00
2011-05-22 08:37:25 +02:00
s -> duration = s -> start_time = AV_NOPTS_VALUE ;
2014-01-16 01:53:03 +01:00
/* Allocate private data. */
2011-05-22 08:37:25 +02:00
if ( s -> iformat -> priv_data_size > 0 ) {
if ( ! ( s -> priv_data = av_mallocz ( s -> iformat -> priv_data_size ))) {
ret = AVERROR ( ENOMEM );
goto fail ;
}
if ( s -> iformat -> priv_class ) {
2014-01-16 01:53:03 +01:00
* ( const AVClass ** ) s -> priv_data = s -> iformat -> priv_class ;
2011-05-22 08:37:25 +02:00
av_opt_set_defaults ( s -> priv_data );
if (( ret = av_opt_set_dict ( s -> priv_data , & tmp )) < 0 )
goto fail ;
}
}
/* e.g. AVFMT_NOFILE formats will not have a AVIOContext */
if ( s -> pb )
2017-01-28 17:25:27 +01:00
ff_id3v2_read_dict ( s -> pb , & s -> internal -> id3v2_meta , ID3v2_DEFAULT_MAGIC , & id3v2_extra_meta );
2021-02-26 17:25:54 +01:00
if ( s -> iformat -> read_header )
2020-03-21 17:23:52 +01:00
if (( ret = s -> iformat -> read_header ( s )) < 0 ) {
if ( s -> iformat -> flags_internal & FF_FMT_INIT_CLEANUP )
goto close ;
2011-05-22 08:37:25 +02:00
goto fail ;
2020-03-21 17:23:52 +01:00
}
2011-05-22 08:37:25 +02:00
2017-01-28 17:25:27 +01:00
if ( ! s -> metadata ) {
s -> metadata = s -> internal -> id3v2_meta ;
s -> internal -> id3v2_meta = NULL ;
} else if ( s -> internal -> id3v2_meta ) {
2020-02-21 12:53:30 -08:00
av_log ( s , AV_LOG_WARNING , "Discarding ID3 tags because more suitable tags were found. \n " );
2017-01-28 17:25:27 +01:00
av_dict_free ( & s -> internal -> id3v2_meta );
}
2012-09-25 02:45:46 +02:00
if ( id3v2_extra_meta ) {
2013-06-16 18:49:51 +00:00
if ( ! strcmp ( s -> iformat -> name , "mp3" ) || ! strcmp ( s -> iformat -> name , "aac" ) ||
2018-12-12 19:24:21 +01:00
! strcmp ( s -> iformat -> name , "tta" ) || ! strcmp ( s -> iformat -> name , "wav" )) {
2020-05-19 12:09:48 +02:00
if (( ret = ff_id3v2_parse_apic ( s , id3v2_extra_meta )) < 0 )
2020-01-07 14:55:47 +01:00
goto close ;
2020-05-19 12:09:48 +02:00
if (( ret = ff_id3v2_parse_chapters ( s , id3v2_extra_meta )) < 0 )
2020-01-07 14:55:47 +01:00
goto close ;
2020-05-19 12:09:48 +02:00
if (( ret = ff_id3v2_parse_priv ( s , id3v2_extra_meta )) < 0 )
2020-01-07 14:55:47 +01:00
goto close ;
2012-09-25 02:45:46 +02:00
} else
2012-09-25 07:42:32 +02:00
av_log ( s , AV_LOG_DEBUG , "demuxer does not support additional id3 data, skipping \n " );
2012-09-25 02:45:46 +02:00
}
2012-02-25 09:53:35 +01:00
ff_id3v2_free_extra_meta ( & id3v2_extra_meta );
2013-03-08 17:28:42 +01:00
if (( ret = avformat_queue_attached_pictures ( s )) < 0 )
2020-01-07 14:55:47 +01:00
goto close ;
2012-02-25 18:05:55 +01:00
2021-02-26 17:25:54 +01:00
if ( s -> pb && ! s -> internal -> data_offset )
2015-02-06 14:53:40 +01:00
s -> internal -> data_offset = avio_tell ( s -> pb );
2011-05-22 08:37:25 +02:00
2015-02-06 14:53:40 +01:00
s -> internal -> raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE ;
2011-05-22 08:37:25 +02:00
2014-06-18 20:42:52 +02:00
update_stream_avctx ( s );
2011-05-22 08:37:25 +02:00
if ( options ) {
av_dict_free ( options );
* options = tmp ;
}
* ps = s ;
return 0 ;
2020-01-07 14:55:47 +01:00
close :
if ( s -> iformat -> read_close )
s -> iformat -> read_close ( s );
2011-05-22 08:37:25 +02:00
fail :
2012-02-25 09:53:35 +01:00
ff_id3v2_free_extra_meta ( & id3v2_extra_meta );
2011-05-22 08:37:25 +02:00
av_dict_free ( & tmp );
if ( s -> pb && ! ( s -> flags & AVFMT_FLAG_CUSTOM_IO ))
2015-01-09 13:39:06 +01:00
avio_closep ( & s -> pb );
2011-05-22 08:37:25 +02:00
avformat_free_context ( s );
* ps = NULL ;
return ret ;
2001-07-22 14:18:56 +00:00
}
2003-10-29 14:20:56 +00:00
/*******************************************************/
2013-01-02 01:15:06 +01:00
static void force_codec_ids ( AVFormatContext * s , AVStream * st )
{
2016-04-10 20:58:15 +01:00
switch ( st -> codecpar -> codec_type ) {
2013-01-02 01:15:06 +01:00
case AVMEDIA_TYPE_VIDEO :
2014-01-26 23:35:38 +01:00
if ( s -> video_codec_id )
2016-04-10 20:58:15 +01:00
st -> codecpar -> codec_id = s -> video_codec_id ;
2013-01-02 01:15:06 +01:00
break ;
case AVMEDIA_TYPE_AUDIO :
2014-01-26 23:35:38 +01:00
if ( s -> audio_codec_id )
2016-04-10 20:58:15 +01:00
st -> codecpar -> codec_id = s -> audio_codec_id ;
2013-01-02 01:15:06 +01:00
break ;
case AVMEDIA_TYPE_SUBTITLE :
2014-01-26 23:35:38 +01:00
if ( s -> subtitle_codec_id )
2016-04-10 20:58:15 +01:00
st -> codecpar -> codec_id = s -> subtitle_codec_id ;
2013-01-02 01:15:06 +01:00
break ;
2016-08-23 12:03:20 +03:00
case AVMEDIA_TYPE_DATA :
if ( s -> data_codec_id )
2016-08-26 15:28:21 -03:00
st -> codecpar -> codec_id = s -> data_codec_id ;
2016-08-23 12:03:20 +03:00
break ;
2013-01-02 01:15:06 +01:00
}
}
2013-09-12 10:39:22 +02:00
static int probe_codec ( AVFormatContext * s , AVStream * st , const AVPacket * pkt )
2012-06-04 16:07:48 -07:00
{
2020-10-09 09:22:36 +02:00
if ( st -> internal -> request_probe > 0 ) {
2020-10-09 09:22:36 +02:00
AVProbeData * pd = & st -> internal -> probe_data ;
2012-06-05 22:43:44 +02:00
int end ;
2021-05-01 23:13:41 -03:00
av_log ( s , AV_LOG_DEBUG , "probing stream %d pp:%d \n " , st -> index , st -> internal -> probe_packets );
-- st -> internal -> probe_packets ;
2012-06-04 16:07:48 -07:00
2012-06-04 16:58:48 -07:00
if ( pkt ) {
2012-07-26 01:05:01 +02:00
uint8_t * new_buf = av_realloc ( pd -> buf , pd -> buf_size + pkt -> size + AVPROBE_PADDING_SIZE );
2014-01-26 23:35:38 +01:00
if ( ! new_buf ) {
2013-09-17 13:09:24 +02:00
av_log ( s , AV_LOG_WARNING ,
"Failed to reallocate probe buffer for stream %d \n " ,
st -> index );
2012-07-26 01:05:01 +02:00
goto no_packet ;
2013-09-17 13:09:24 +02:00
}
2012-07-26 01:05:01 +02:00
pd -> buf = new_buf ;
2014-01-16 01:53:03 +01:00
memcpy ( pd -> buf + pd -> buf_size , pkt -> data , pkt -> size );
2012-06-04 16:58:48 -07:00
pd -> buf_size += pkt -> size ;
2014-01-16 01:53:03 +01:00
memset ( pd -> buf + pd -> buf_size , 0 , AVPROBE_PADDING_SIZE );
2012-06-04 16:58:48 -07:00
} else {
2012-07-26 01:05:01 +02:00
no_packet :
2021-05-01 23:13:41 -03:00
st -> internal -> probe_packets = 0 ;
2012-09-07 16:27:21 +02:00
if ( ! pd -> buf_size ) {
2014-01-26 23:35:38 +01:00
av_log ( s , AV_LOG_WARNING ,
2014-01-16 01:53:03 +01:00
"nothing to probe for stream %d \n " , st -> index );
2012-09-07 16:27:21 +02:00
}
2012-06-04 16:58:48 -07:00
}
2012-06-04 16:07:48 -07:00
2015-02-11 02:13:46 +01:00
end = s -> internal -> raw_packet_buffer_remaining_size <= 0
2021-05-01 23:13:41 -03:00
|| st -> internal -> probe_packets <= 0 ;
2012-06-05 22:43:44 +02:00
2014-01-26 23:35:38 +01:00
if ( end || av_log2 ( pd -> buf_size ) != av_log2 ( pd -> buf_size - pkt -> size )) {
int score = set_codec_from_probe_data ( s , st , pd );
2016-04-10 20:58:15 +01:00
if ( ( st -> codecpar -> codec_id != AV_CODEC_ID_NONE && score > AVPROBE_SCORE_STREAM_RETRY )
2014-01-26 23:35:38 +01:00
|| end ) {
2014-01-16 01:53:03 +01:00
pd -> buf_size = 0 ;
2012-06-04 16:07:48 -07:00
av_freep ( & pd -> buf );
2020-10-09 09:22:36 +02:00
st -> internal -> request_probe = - 1 ;
2016-04-10 20:58:15 +01:00
if ( st -> codecpar -> codec_id != AV_CODEC_ID_NONE ) {
2012-06-05 22:43:44 +02:00
av_log ( s , AV_LOG_DEBUG , "probed stream %d \n " , st -> index );
2014-01-26 23:35:38 +01:00
} else
2012-06-05 22:43:44 +02:00
av_log ( s , AV_LOG_WARNING , "probed stream %d failed \n " , st -> index );
2012-06-04 16:07:48 -07:00
}
2013-01-02 01:15:58 +01:00
force_codec_ids ( s , st );
2012-06-04 16:07:48 -07:00
}
}
2013-09-12 10:39:22 +02:00
return 0 ;
2012-06-04 16:07:48 -07:00
}
2013-12-04 14:34:05 +01:00
static int update_wrap_reference ( AVFormatContext * s , AVStream * st , int stream_index , AVPacket * pkt )
{
int64_t ref = pkt -> dts ;
int i , pts_wrap_behavior ;
int64_t pts_wrap_reference ;
AVProgram * first_program ;
if ( ref == AV_NOPTS_VALUE )
ref = pkt -> pts ;
2020-10-09 09:22:36 +02:00
if ( st -> internal -> pts_wrap_reference != AV_NOPTS_VALUE || st -> pts_wrap_bits >= 63 || ref == AV_NOPTS_VALUE || ! s -> correct_ts_overflow )
2013-12-04 14:34:05 +01:00
return 0 ;
2014-01-26 23:35:38 +01:00
ref &= ( 1LL << st -> pts_wrap_bits ) - 1 ;
2013-12-04 14:34:05 +01:00
// reference time stamp should be 60 s before first time stamp
pts_wrap_reference = ref - av_rescale ( 60 , st -> time_base . den , st -> time_base . num );
// if first time stamp is not more than 1/8 and 60s before the wrap point, subtract rather than add wrap offset
2014-01-26 23:35:38 +01:00
pts_wrap_behavior = ( ref < ( 1LL << st -> pts_wrap_bits ) - ( 1LL << st -> pts_wrap_bits - 3 )) ||
( ref < ( 1LL << st -> pts_wrap_bits ) - av_rescale ( 60 , st -> time_base . den , st -> time_base . num )) ?
2013-12-04 14:34:05 +01:00
AV_PTS_WRAP_ADD_OFFSET : AV_PTS_WRAP_SUB_OFFSET ;
first_program = av_find_program_from_stream ( s , NULL , stream_index );
if ( ! first_program ) {
int default_stream_index = av_find_default_stream_index ( s );
2020-10-09 09:22:36 +02:00
if ( s -> streams [ default_stream_index ] -> internal -> pts_wrap_reference == AV_NOPTS_VALUE ) {
2014-01-26 23:35:38 +01:00
for ( i = 0 ; i < s -> nb_streams ; i ++ ) {
2014-12-14 19:46:31 +01:00
if ( av_find_program_from_stream ( s , NULL , i ))
continue ;
2020-10-09 09:22:36 +02:00
s -> streams [ i ] -> internal -> pts_wrap_reference = pts_wrap_reference ;
s -> streams [ i ] -> internal -> pts_wrap_behavior = pts_wrap_behavior ;
2013-12-04 14:34:05 +01:00
}
}
else {
2020-10-09 09:22:36 +02:00
st -> internal -> pts_wrap_reference = s -> streams [ default_stream_index ] -> internal -> pts_wrap_reference ;
st -> internal -> pts_wrap_behavior = s -> streams [ default_stream_index ] -> internal -> pts_wrap_behavior ;
2013-12-04 14:34:05 +01:00
}
}
else {
AVProgram * program = first_program ;
while ( program ) {
if ( program -> pts_wrap_reference != AV_NOPTS_VALUE ) {
pts_wrap_reference = program -> pts_wrap_reference ;
pts_wrap_behavior = program -> pts_wrap_behavior ;
break ;
}
program = av_find_program_from_stream ( s , program , stream_index );
}
// update every program with differing pts_wrap_reference
program = first_program ;
2014-01-26 23:35:38 +01:00
while ( program ) {
2013-12-04 14:34:05 +01:00
if ( program -> pts_wrap_reference != pts_wrap_reference ) {
2014-01-26 23:35:38 +01:00
for ( i = 0 ; i < program -> nb_stream_indexes ; i ++ ) {
2020-10-09 09:22:36 +02:00
s -> streams [ program -> stream_index [ i ]] -> internal -> pts_wrap_reference = pts_wrap_reference ;
s -> streams [ program -> stream_index [ i ]] -> internal -> pts_wrap_behavior = pts_wrap_behavior ;
2013-12-04 14:34:05 +01:00
}
program -> pts_wrap_reference = pts_wrap_reference ;
program -> pts_wrap_behavior = pts_wrap_behavior ;
}
program = av_find_program_from_stream ( s , program , stream_index );
}
}
return 1 ;
}
2012-03-04 21:41:59 +01:00
int ff_read_packet ( AVFormatContext * s , AVPacket * pkt )
2003-11-10 18:37:55 +00:00
{
2021-03-12 11:00:32 +01:00
int err , i ;
2007-12-19 10:56:17 +00:00
AVStream * st ;
2008-07-12 18:42:00 +00:00
2021-01-31 13:05:49 -03:00
#if FF_API_INIT_PACKET
FF_DISABLE_DEPRECATION_WARNINGS
2019-09-20 22:39:11 +02:00
pkt -> data = NULL ;
pkt -> size = 0 ;
av_init_packet ( pkt );
2021-01-31 13:05:49 -03:00
FF_ENABLE_DEPRECATION_WARNINGS
#else
av_packet_unref ( pkt );
#endif
2019-09-20 22:39:11 +02:00
2014-01-16 01:53:03 +01:00
for (;;) {
2021-03-05 11:26:24 -03:00
PacketList * pktl = s -> internal -> raw_packet_buffer ;
2019-09-20 22:39:10 +02:00
const AVPacket * pkt1 ;
2008-07-12 18:42:00 +00:00
if ( pktl ) {
2019-08-19 23:56:19 +02:00
st = s -> streams [ pktl -> pkt . stream_index ];
2015-02-11 02:13:46 +01:00
if ( s -> internal -> raw_packet_buffer_remaining_size <= 0 )
2013-09-17 12:37:04 +02:00
if (( err = probe_codec ( s , st , NULL )) < 0 )
return err ;
2020-10-09 09:22:36 +02:00
if ( st -> internal -> request_probe <= 0 ) {
2020-08-17 12:03:50 -03:00
avpriv_packet_list_get ( & s -> internal -> raw_packet_buffer ,
2019-08-19 23:56:19 +02:00
& s -> internal -> raw_packet_buffer_end , pkt );
2015-02-06 14:53:40 +01:00
s -> internal -> raw_packet_buffer_remaining_size += pkt -> size ;
2008-07-12 18:42:00 +00:00
return 0 ;
}
}
2021-03-12 11:00:32 +01:00
err = s -> iformat -> read_packet ( s , pkt );
if ( err < 0 ) {
2019-09-20 22:39:09 +02:00
av_packet_unref ( pkt );
2015-11-27 18:57:27 +01:00
/* Some demuxers return FFERROR_REDO when they consume
data and discard it (ignored streams, junk, extradata).
We must re-call the demuxer to get the real packet. */
2021-03-12 11:00:32 +01:00
if ( err == FFERROR_REDO )
2015-11-27 18:57:27 +01:00
continue ;
2021-03-12 11:00:32 +01:00
if ( ! pktl || err == AVERROR ( EAGAIN ))
return err ;
2012-06-04 16:58:48 -07:00
for ( i = 0 ; i < s -> nb_streams ; i ++ ) {
st = s -> streams [ i ];
2021-05-01 23:13:41 -03:00
if ( st -> internal -> probe_packets || st -> internal -> request_probe > 0 )
2013-09-12 10:39:22 +02:00
if (( err = probe_codec ( s , st , NULL )) < 0 )
return err ;
2020-10-09 09:22:36 +02:00
av_assert0 ( st -> internal -> request_probe <= 0 );
2012-06-04 16:58:48 -07:00
}
2009-05-31 00:24:06 +00:00
continue ;
}
2011-04-20 03:25:48 +02:00
2018-03-24 22:33:32 -03:00
err = av_packet_make_refcounted ( pkt );
2019-09-24 18:31:44 +02:00
if ( err < 0 ) {
av_packet_unref ( pkt );
2018-03-24 22:33:32 -03:00
return err ;
2019-09-24 18:31:44 +02:00
}
2015-10-23 11:11:30 +02:00
2019-09-18 10:37:16 +05:30
if ( pkt -> flags & AV_PKT_FLAG_CORRUPT ) {
2011-07-24 17:28:33 +03:00
av_log ( s , AV_LOG_WARNING ,
2019-09-18 10:37:16 +05:30
"Packet corrupt (stream = %d, dts = %s)" ,
pkt -> stream_index , av_ts2str ( pkt -> dts ));
if ( s -> flags & AVFMT_FLAG_DISCARD_CORRUPT ) {
av_log ( s , AV_LOG_WARNING , ", dropping it. \n " );
av_packet_unref ( pkt );
continue ;
}
av_log ( s , AV_LOG_WARNING , ". \n " );
2011-07-24 17:28:33 +03:00
}
2019-09-24 18:31:43 +02:00
av_assert0 ( pkt -> stream_index < ( unsigned ) s -> nb_streams &&
"Invalid stream index. \n " );
2011-10-12 01:04:12 +02:00
2014-01-26 23:35:38 +01:00
st = s -> streams [ pkt -> stream_index ];
2013-12-04 02:00:23 +01:00
2020-10-09 09:22:36 +02:00
if ( update_wrap_reference ( s , st , pkt -> stream_index , pkt ) && st -> internal -> pts_wrap_behavior == AV_PTS_WRAP_SUB_OFFSET ) {
2013-12-04 02:00:23 +01:00
// correct first time stamps to negative values
2021-06-05 11:12:03 -03:00
if ( ! is_relative ( st -> internal -> first_dts ))
st -> internal -> first_dts = wrap_timestamp ( st , st -> internal -> first_dts );
2013-12-04 02:00:23 +01:00
if ( ! is_relative ( st -> start_time ))
st -> start_time = wrap_timestamp ( st , st -> start_time );
2021-06-05 11:12:03 -03:00
if ( ! is_relative ( st -> internal -> cur_dts ))
st -> internal -> cur_dts = wrap_timestamp ( st , st -> internal -> cur_dts );
2013-12-04 02:00:23 +01:00
}
2012-12-02 19:27:21 +01:00
pkt -> dts = wrap_timestamp ( st , pkt -> dts );
pkt -> pts = wrap_timestamp ( st , pkt -> pts );
2007-12-19 10:56:17 +00:00
2012-09-07 13:16:04 +02:00
force_codec_ids ( s , st );
2012-08-17 00:08:51 +02:00
/* TODO: audio: time filter; video: frame reordering (pts != dts) */
if ( s -> use_wallclock_as_timestamps )
pkt -> dts = pkt -> pts = av_rescale_q ( av_gettime (), AV_TIME_BASE_Q , st -> time_base );
2007-12-19 10:56:17 +00:00
2020-10-09 09:22:36 +02:00
if ( ! pktl && st -> internal -> request_probe <= 0 )
2021-03-12 11:00:32 +01:00
return 0 ;
2008-07-14 20:31:17 +00:00
2020-08-17 12:03:50 -03:00
err = avpriv_packet_list_put ( & s -> internal -> raw_packet_buffer ,
2018-03-27 19:48:18 -03:00
& s -> internal -> raw_packet_buffer_end ,
2020-08-17 12:03:50 -03:00
pkt , NULL , 0 );
2019-09-24 18:31:44 +02:00
if ( err < 0 ) {
av_packet_unref ( pkt );
2015-10-23 11:11:32 +02:00
return err ;
2019-09-24 18:31:44 +02:00
}
2019-09-20 22:39:10 +02:00
pkt1 = & s -> internal -> raw_packet_buffer_end -> pkt ;
s -> internal -> raw_packet_buffer_remaining_size -= pkt1 -> size ;
2008-07-14 20:31:17 +00:00
2019-09-20 22:39:10 +02:00
if (( err = probe_codec ( s , st , pkt1 )) < 0 )
2013-09-12 10:39:22 +02:00
return err ;
2008-07-12 18:42:00 +00:00
}
2003-11-10 18:37:55 +00:00
}
2012-03-04 21:41:59 +01:00
2003-11-10 18:37:55 +00:00
/**********************************************************/
2012-03-04 04:06:15 +01:00
static int determinable_frame_size ( AVCodecContext * avctx )
{
2017-06-04 02:25:46 +02:00
switch ( avctx -> codec_id ) {
case AV_CODEC_ID_MP1 :
case AV_CODEC_ID_MP2 :
case AV_CODEC_ID_MP3 :
2017-08-08 15:28:06 +02:00
case AV_CODEC_ID_CODEC2 :
2012-03-04 04:06:15 +01:00
return 1 ;
2017-06-04 02:25:46 +02:00
}
2012-03-04 04:06:15 +01:00
return 0 ;
}
2005-06-28 12:55:08 +00:00
/**
2008-01-16 22:14:26 +00:00
* Return the frame duration in seconds. Return 0 if not available.
2005-06-28 12:55:08 +00:00
*/
2014-10-08 19:23:14 +00:00
void ff_compute_frame_duration ( AVFormatContext * s , int * pnum , int * pden , AVStream * st ,
2012-10-01 00:49:16 +02:00
AVCodecParserContext * pc , AVPacket * pkt )
2003-11-10 18:37:55 +00:00
{
2014-06-18 20:42:52 +02:00
AVRational codec_framerate = s -> iformat ? st -> internal -> avctx -> framerate :
2016-04-10 20:58:15 +01:00
av_mul_q ( av_inv_q ( st -> internal -> avctx -> time_base ), ( AVRational ){ 1 , st -> internal -> avctx -> ticks_per_frame });
int frame_size , sample_rate ;
2003-11-10 18:37:55 +00:00
* pnum = 0 ;
* pden = 0 ;
2014-06-18 20:42:52 +02:00
switch ( st -> codecpar -> codec_type ) {
2010-03-30 23:30:55 +00:00
case AVMEDIA_TYPE_VIDEO :
2014-12-14 01:36:29 +01:00
if ( st -> r_frame_rate . num && ! pc && s -> iformat ) {
2011-11-28 10:02:21 +01:00
* pnum = st -> r_frame_rate . den ;
* pden = st -> r_frame_rate . num ;
2014-01-16 01:53:03 +01:00
} else if ( st -> time_base . num * 1000LL > st -> time_base . den ) {
2005-04-30 21:43:59 +00:00
* pnum = st -> time_base . num ;
* pden = st -> time_base . den ;
2014-10-08 19:23:14 +00:00
} else if ( codec_framerate . den * 1000LL > codec_framerate . num ) {
2016-04-10 20:58:15 +01:00
av_assert0 ( st -> internal -> avctx -> ticks_per_frame );
2014-10-15 18:23:21 +02:00
av_reduce ( pnum , pden ,
codec_framerate . den ,
2016-04-10 20:58:15 +01:00
codec_framerate . num * ( int64_t ) st -> internal -> avctx -> ticks_per_frame ,
2014-10-15 18:23:21 +02:00
INT_MAX );
2005-05-06 20:26:50 +00:00
if ( pc && pc -> repeat_pict ) {
2014-10-15 16:24:43 +02:00
av_assert0 ( s -> iformat ); // this may be wrong for interlaced encoding but its not used for that case
2014-10-15 18:23:21 +02:00
av_reduce ( pnum , pden ,
( * pnum ) * ( 1LL + pc -> repeat_pict ),
( * pden ),
INT_MAX );
2005-05-06 20:26:50 +00:00
}
2014-01-16 01:53:03 +01:00
/* If this codec can be interlaced or progressive then we need
* a parser to compute duration of a packet. Thus if we have
* no parser in such case leave duration undefined. */
2014-06-18 20:42:52 +02:00
if ( st -> internal -> avctx -> ticks_per_frame > 1 && ! pc )
2010-04-09 22:39:39 +00:00
* pnum = * pden = 0 ;
2003-11-10 18:37:55 +00:00
}
break ;
2010-03-30 23:30:55 +00:00
case AVMEDIA_TYPE_AUDIO :
2016-04-10 20:58:15 +01:00
if ( st -> internal -> avctx_inited ) {
frame_size = av_get_audio_frame_duration ( st -> internal -> avctx , pkt -> size );
sample_rate = st -> internal -> avctx -> sample_rate ;
} else {
frame_size = av_get_audio_frame_duration2 ( st -> codecpar , pkt -> size );
sample_rate = st -> codecpar -> sample_rate ;
}
if ( frame_size <= 0 || sample_rate <= 0 )
2003-11-10 18:37:55 +00:00
break ;
* pnum = frame_size ;
2016-04-10 20:58:15 +01:00
* pden = sample_rate ;
2003-11-10 18:37:55 +00:00
break ;
default :
break ;
}
}
2020-04-21 23:35:23 +08:00
int ff_is_intra_only ( enum AVCodecID id )
2012-08-09 18:39:56 +02:00
{
const AVCodecDescriptor * d = avcodec_descriptor_get ( id );
if ( ! d )
return 0 ;
2019-12-12 23:02:01 +09:00
if (( d -> type == AVMEDIA_TYPE_VIDEO || d -> type == AVMEDIA_TYPE_AUDIO ) &&
! ( d -> props & AV_CODEC_PROP_INTRA_ONLY ))
2012-08-09 18:39:56 +02:00
return 0 ;
return 1 ;
2004-10-22 01:51:17 +00:00
}
2012-08-04 15:35:53 +02:00
static int has_decode_delay_been_guessed ( AVStream * st )
{
2016-04-10 20:58:15 +01:00
if ( st -> codecpar -> codec_id != AV_CODEC_ID_H264 ) return 1 ;
2020-10-09 08:15:27 +02:00
if ( ! st -> internal -> info ) // if we have left find_stream_info then nb_decoded_frames won't increase anymore for stream copy
2012-09-26 04:53:03 +02:00
return 1 ;
2012-08-04 15:35:53 +02:00
#if CONFIG_H264_DECODER
2016-04-10 20:58:15 +01:00
if ( st -> internal -> avctx -> has_b_frames &&
avpriv_h264_has_num_reorder_frames ( st -> internal -> avctx ) == st -> internal -> avctx -> has_b_frames )
2012-08-04 15:35:53 +02:00
return 1 ;
#endif
2016-04-10 20:58:15 +01:00
if ( st -> internal -> avctx -> has_b_frames < 3 )
2020-10-09 09:22:36 +02:00
return st -> internal -> nb_decoded_frames >= 7 ;
2016-04-10 20:58:15 +01:00
else if ( st -> internal -> avctx -> has_b_frames < 4 )
2020-10-09 09:22:36 +02:00
return st -> internal -> nb_decoded_frames >= 18 ;
2012-08-04 15:35:53 +02:00
else
2020-10-09 09:22:36 +02:00
return st -> internal -> nb_decoded_frames >= 20 ;
2012-08-04 15:35:53 +02:00
}
2021-03-05 11:26:24 -03:00
static PacketList * get_next_pkt ( AVFormatContext * s , AVStream * st , PacketList * pktl )
2012-03-06 03:56:25 +01:00
{
if ( pktl -> next )
return pktl -> next ;
2015-02-11 02:13:46 +01:00
if ( pktl == s -> internal -> packet_buffer_end )
return s -> internal -> parse_queue ;
2012-03-06 03:56:25 +01:00
return NULL ;
}
2014-02-22 13:04:18 +01:00
static int64_t select_from_pts_buffer ( AVStream * st , int64_t * pts_buffer , int64_t dts ) {
2016-04-10 20:58:15 +01:00
int onein_oneout = st -> codecpar -> codec_id != AV_CODEC_ID_H264 &&
st -> codecpar -> codec_id != AV_CODEC_ID_HEVC ;
2014-02-22 13:04:18 +01:00
if ( ! onein_oneout ) {
2016-04-10 20:58:15 +01:00
int delay = st -> internal -> avctx -> has_b_frames ;
2014-02-22 13:04:18 +01:00
int i ;
if ( dts == AV_NOPTS_VALUE ) {
int64_t best_score = INT64_MAX ;
for ( i = 0 ; i < delay ; i ++ ) {
2020-10-09 09:22:36 +02:00
if ( st -> internal -> pts_reorder_error_count [ i ]) {
int64_t score = st -> internal -> pts_reorder_error [ i ] / st -> internal -> pts_reorder_error_count [ i ];
2014-02-22 13:04:18 +01:00
if ( score < best_score ) {
best_score = score ;
dts = pts_buffer [ i ];
}
}
}
} else {
for ( i = 0 ; i < delay ; i ++ ) {
if ( pts_buffer [ i ] != AV_NOPTS_VALUE ) {
int64_t diff = FFABS ( pts_buffer [ i ] - dts )
2020-10-09 09:22:36 +02:00
+ ( uint64_t ) st -> internal -> pts_reorder_error [ i ];
diff = FFMAX ( diff , st -> internal -> pts_reorder_error [ i ]);
st -> internal -> pts_reorder_error [ i ] = diff ;
st -> internal -> pts_reorder_error_count [ i ] ++ ;
if ( st -> internal -> pts_reorder_error_count [ i ] > 250 ) {
st -> internal -> pts_reorder_error [ i ] >>= 1 ;
st -> internal -> pts_reorder_error_count [ i ] >>= 1 ;
2014-02-22 13:04:18 +01:00
}
}
}
}
}
if ( dts == AV_NOPTS_VALUE )
dts = pts_buffer [ 0 ];
return dts ;
}
2016-03-12 02:40:25 -08:00
/**
* Updates the dts of packets of a stream in pkt_buffer, by re-ordering the pts
* of the packets in a window.
*/
static void update_dts_from_pts ( AVFormatContext * s , int stream_index ,
2021-03-05 11:26:24 -03:00
PacketList * pkt_buffer )
2016-03-12 02:40:25 -08:00
{
AVStream * st = s -> streams [ stream_index ];
2016-04-10 20:58:15 +01:00
int delay = st -> internal -> avctx -> has_b_frames ;
2016-03-12 02:40:25 -08:00
int i ;
int64_t pts_buffer [ MAX_REORDER_DELAY + 1 ];
for ( i = 0 ; i < MAX_REORDER_DELAY + 1 ; i ++ )
pts_buffer [ i ] = AV_NOPTS_VALUE ;
for (; pkt_buffer ; pkt_buffer = get_next_pkt ( s , st , pkt_buffer )) {
if ( pkt_buffer -> pkt . stream_index != stream_index )
continue ;
if ( pkt_buffer -> pkt . pts != AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY ) {
pts_buffer [ 0 ] = pkt_buffer -> pkt . pts ;
for ( i = 0 ; i < delay && pts_buffer [ i ] > pts_buffer [ i + 1 ]; i ++ )
FFSWAP ( int64_t , pts_buffer [ i ], pts_buffer [ i + 1 ]);
pkt_buffer -> pkt . dts = select_from_pts_buffer ( st , pts_buffer , pkt_buffer -> pkt . dts );
}
}
}
2007-09-03 07:56:26 +00:00
static void update_initial_timestamps ( AVFormatContext * s , int stream_index ,
2012-12-02 19:27:21 +01:00
int64_t dts , int64_t pts , AVPacket * pkt )
2007-09-03 07:56:26 +00:00
{
2014-01-16 01:53:03 +01:00
AVStream * st = s -> streams [ stream_index ];
2021-03-05 11:26:24 -03:00
PacketList * pktl = s -> internal -> packet_buffer ? s -> internal -> packet_buffer : s -> internal -> parse_queue ;
PacketList * pktl_it ;
2016-03-12 02:40:25 -08:00
2015-12-03 21:54:43 +01:00
uint64_t shift ;
2007-08-04 22:46:13 +00:00
2021-06-05 11:12:03 -03:00
if ( st -> internal -> first_dts != AV_NOPTS_VALUE ||
2014-01-16 01:53:03 +01:00
dts == AV_NOPTS_VALUE ||
2021-06-05 11:12:03 -03:00
st -> internal -> cur_dts == AV_NOPTS_VALUE ||
st -> internal -> cur_dts < INT_MIN + RELATIVE_TS_BASE ||
dts < INT_MIN + ( st -> internal -> cur_dts - RELATIVE_TS_BASE ) ||
2014-01-26 23:35:38 +01:00
is_relative ( dts ))
2007-08-04 22:46:13 +00:00
return ;
2021-06-05 11:12:03 -03:00
st -> internal -> first_dts = dts - ( st -> internal -> cur_dts - RELATIVE_TS_BASE );
st -> internal -> cur_dts = dts ;
shift = ( uint64_t ) st -> internal -> first_dts - RELATIVE_TS_BASE ;
2007-08-04 22:46:13 +00:00
2012-03-07 22:13:39 +01:00
if ( is_relative ( pts ))
2012-09-26 22:52:33 +02:00
pts += shift ;
2012-03-07 22:13:39 +01:00
2016-03-12 02:40:25 -08:00
for ( pktl_it = pktl ; pktl_it ; pktl_it = get_next_pkt ( s , st , pktl_it )) {
if ( pktl_it -> pkt . stream_index != stream_index )
2007-08-04 22:46:13 +00:00
continue ;
2016-03-12 02:40:25 -08:00
if ( is_relative ( pktl_it -> pkt . pts ))
pktl_it -> pkt . pts += shift ;
2007-08-04 22:46:13 +00:00
2016-03-12 02:40:25 -08:00
if ( is_relative ( pktl_it -> pkt . dts ))
pktl_it -> pkt . dts += shift ;
2007-08-04 22:54:46 +00:00
2016-02-20 22:39:07 +01:00
if ( st -> start_time == AV_NOPTS_VALUE && pktl_it -> pkt . pts != AV_NOPTS_VALUE ) {
2016-03-12 02:40:25 -08:00
st -> start_time = pktl_it -> pkt . pts ;
2016-04-10 20:58:15 +01:00
if ( st -> codecpar -> codec_type == AVMEDIA_TYPE_AUDIO && st -> codecpar -> sample_rate )
2020-10-09 09:22:36 +02:00
st -> start_time = av_sat_add64 ( st -> start_time , av_rescale_q ( st -> internal -> skip_samples , ( AVRational ){ 1 , st -> codecpar -> sample_rate }, st -> time_base ));
2016-02-20 22:39:07 +01:00
}
2016-03-12 02:40:25 -08:00
}
2012-09-26 22:54:57 +02:00
2016-03-12 02:40:25 -08:00
if ( has_decode_delay_been_guessed ( st )) {
update_dts_from_pts ( s , stream_index , pktl );
2007-08-04 22:46:13 +00:00
}
2012-12-02 19:27:21 +01:00
2016-02-20 22:39:07 +01:00
if ( st -> start_time == AV_NOPTS_VALUE ) {
2018-03-21 13:36:38 -07:00
if ( st -> codecpar -> codec_type == AVMEDIA_TYPE_AUDIO || ! ( pkt -> flags & AV_PKT_FLAG_DISCARD )) {
st -> start_time = pts ;
}
2016-04-10 20:58:15 +01:00
if ( st -> codecpar -> codec_type == AVMEDIA_TYPE_AUDIO && st -> codecpar -> sample_rate )
2020-10-09 09:22:36 +02:00
st -> start_time = av_sat_add64 ( st -> start_time , av_rescale_q ( st -> internal -> skip_samples , ( AVRational ){ 1 , st -> codecpar -> sample_rate }, st -> time_base ));
2016-02-20 22:39:07 +01:00
}
2007-08-04 22:46:13 +00:00
}
2012-02-27 18:07:07 -05:00
static void update_initial_durations ( AVFormatContext * s , AVStream * st ,
2020-04-29 07:49:24 +08:00
int stream_index , int64_t duration )
2008-02-15 20:32:32 +00:00
{
2021-03-05 11:26:24 -03:00
PacketList * pktl = s -> internal -> packet_buffer ? s -> internal -> packet_buffer : s -> internal -> parse_queue ;
2014-01-26 23:35:38 +01:00
int64_t cur_dts = RELATIVE_TS_BASE ;
2008-02-15 20:32:32 +00:00
2021-06-05 11:12:03 -03:00
if ( st -> internal -> first_dts != AV_NOPTS_VALUE ) {
2020-10-09 09:22:36 +02:00
if ( st -> internal -> update_initial_durations_done )
2013-12-31 08:36:14 +01:00
return ;
2020-10-09 09:22:36 +02:00
st -> internal -> update_initial_durations_done = 1 ;
2021-06-05 11:12:03 -03:00
cur_dts = st -> internal -> first_dts ;
2014-01-26 23:35:38 +01:00
for (; pktl ; pktl = get_next_pkt ( s , st , pktl )) {
2014-01-16 01:53:03 +01:00
if ( pktl -> pkt . stream_index == stream_index ) {
if ( pktl -> pkt . pts != pktl -> pkt . dts ||
pktl -> pkt . dts != AV_NOPTS_VALUE ||
pktl -> pkt . duration )
2008-06-03 00:50:22 +00:00
break ;
2012-02-27 18:07:07 -05:00
cur_dts -= duration ;
2008-06-03 00:50:22 +00:00
}
}
2021-06-05 11:12:03 -03:00
if ( pktl && pktl -> pkt . dts != st -> internal -> first_dts ) {
2015-09-29 15:14:59 +02:00
av_log ( s , AV_LOG_DEBUG , "first_dts %s not matching first dts %s (pts %s, duration %" PRId64 ") in the queue \n " ,
2021-06-05 11:12:03 -03:00
av_ts2str ( st -> internal -> first_dts ), av_ts2str ( pktl -> pkt . dts ), av_ts2str ( pktl -> pkt . pts ), pktl -> pkt . duration );
2012-05-14 17:14:44 +02:00
return ;
}
2014-01-26 23:35:38 +01:00
if ( ! pktl ) {
2021-06-05 11:12:03 -03:00
av_log ( s , AV_LOG_DEBUG , "first_dts %s but no packet with dts in the queue \n " , av_ts2str ( st -> internal -> first_dts ));
2012-05-14 17:14:44 +02:00
return ;
}
2015-02-11 02:13:46 +01:00
pktl = s -> internal -> packet_buffer ? s -> internal -> packet_buffer : s -> internal -> parse_queue ;
2021-06-05 11:12:03 -03:00
st -> internal -> first_dts = cur_dts ;
} else if ( st -> internal -> cur_dts != RELATIVE_TS_BASE )
2008-06-03 00:50:22 +00:00
return ;
2008-02-15 20:32:32 +00:00
2014-01-26 23:35:38 +01:00
for (; pktl ; pktl = get_next_pkt ( s , st , pktl )) {
2014-01-16 01:53:03 +01:00
if ( pktl -> pkt . stream_index != stream_index )
2008-02-15 20:32:32 +00:00
continue ;
2017-02-19 00:31:09 +01:00
if (( pktl -> pkt . pts == pktl -> pkt . dts ||
pktl -> pkt . pts == AV_NOPTS_VALUE ) &&
( pktl -> pkt . dts == AV_NOPTS_VALUE ||
2021-06-05 11:12:03 -03:00
pktl -> pkt . dts == st -> internal -> first_dts ||
2017-02-19 00:31:09 +01:00
pktl -> pkt . dts == RELATIVE_TS_BASE ) &&
2021-04-18 22:39:30 +02:00
! pktl -> pkt . duration &&
av_sat_add64 ( cur_dts , duration ) == cur_dts + ( uint64_t ) duration
) {
2014-01-16 01:53:03 +01:00
pktl -> pkt . dts = cur_dts ;
2014-06-18 20:42:52 +02:00
if ( ! st -> internal -> avctx -> has_b_frames )
2014-01-16 01:53:03 +01:00
pktl -> pkt . pts = cur_dts ;
2020-10-13 15:59:06 +11:00
pktl -> pkt . duration = duration ;
2014-01-16 01:53:03 +01:00
} else
2008-02-15 20:32:32 +00:00
break ;
2012-03-02 06:22:20 +01:00
cur_dts = pktl -> pkt . dts + pktl -> pkt . duration ;
2008-02-15 20:32:32 +00:00
}
2014-01-26 23:35:38 +01:00
if ( ! pktl )
2021-06-05 11:12:03 -03:00
st -> internal -> cur_dts = cur_dts ;
2008-02-15 20:32:32 +00:00
}
2005-12-17 18:14:38 +00:00
static void compute_pkt_fields ( AVFormatContext * s , AVStream * st ,
2014-12-09 03:33:44 +01:00
AVCodecParserContext * pc , AVPacket * pkt ,
int64_t next_dts , int64_t next_pts )
2003-11-10 18:37:55 +00:00
{
2007-03-17 14:27:01 +00:00
int num , den , presentation_delayed , delay , i ;
2007-04-13 07:50:04 +00:00
int64_t offset ;
2014-01-03 17:44:15 +01:00
AVRational duration ;
2016-04-10 20:58:15 +01:00
int onein_oneout = st -> codecpar -> codec_id != AV_CODEC_ID_H264 &&
st -> codecpar -> codec_id != AV_CODEC_ID_HEVC ;
2005-12-17 18:14:38 +00:00
2010-03-31 12:55:16 +00:00
if ( s -> flags & AVFMT_FLAG_NOFILLIN )
return ;
2016-04-10 20:58:15 +01:00
if ( st -> codecpar -> codec_type == AVMEDIA_TYPE_VIDEO && pkt -> dts != AV_NOPTS_VALUE ) {
2020-10-09 09:22:36 +02:00
if ( pkt -> dts == pkt -> pts && st -> internal -> last_dts_for_order_check != AV_NOPTS_VALUE ) {
if ( st -> internal -> last_dts_for_order_check <= pkt -> dts ) {
st -> internal -> dts_ordered ++ ;
2014-03-03 01:55:18 +01:00
} else {
2020-10-09 09:22:36 +02:00
av_log ( s , st -> internal -> dts_misordered ? AV_LOG_DEBUG : AV_LOG_WARNING ,
2014-03-03 01:55:18 +01:00
"DTS %" PRIi64 " < %" PRIi64 " out of order \n " ,
pkt -> dts ,
2020-10-09 09:22:36 +02:00
st -> internal -> last_dts_for_order_check );
st -> internal -> dts_misordered ++ ;
2014-03-03 01:55:18 +01:00
}
2020-10-09 09:22:36 +02:00
if ( st -> internal -> dts_ordered + st -> internal -> dts_misordered > 250 ) {
st -> internal -> dts_ordered >>= 1 ;
st -> internal -> dts_misordered >>= 1 ;
2014-03-03 01:55:18 +01:00
}
}
2020-10-09 09:22:36 +02:00
st -> internal -> last_dts_for_order_check = pkt -> dts ;
if ( st -> internal -> dts_ordered < 8 * st -> internal -> dts_misordered && pkt -> dts == pkt -> pts )
2014-03-03 01:55:18 +01:00
pkt -> dts = AV_NOPTS_VALUE ;
}
2014-01-16 01:53:03 +01:00
if (( s -> flags & AVFMT_FLAG_IGNDTS ) && pkt -> pts != AV_NOPTS_VALUE )
pkt -> dts = AV_NOPTS_VALUE ;
2010-01-30 22:55:12 +00:00
2013-11-03 21:26:40 +01:00
if ( pc && pc -> pict_type == AV_PICTURE_TYPE_B
2016-04-10 20:58:15 +01:00
&& ! st -> internal -> avctx -> has_b_frames )
2009-10-03 19:40:52 +00:00
//FIXME Set low_delay = 0 when has_b_frames = 1
2016-04-10 20:58:15 +01:00
st -> internal -> avctx -> has_b_frames = 1 ;
2009-06-11 04:30:05 +00:00
2008-10-18 22:41:21 +00:00
/* do we have a video B-frame ? */
2014-06-18 20:42:52 +02:00
delay = st -> internal -> avctx -> has_b_frames ;
2008-10-18 22:41:21 +00:00
presentation_delayed = 0 ;
2011-02-07 21:15:44 -05:00
2008-10-18 22:41:21 +00:00
/* XXX: need has_b_frame, but cannot get it if the codec is
2014-01-16 01:53:03 +01:00
* not initialized */
2008-10-18 22:41:21 +00:00
if ( delay &&
2011-04-28 01:40:44 +02:00
pc && pc -> pict_type != AV_PICTURE_TYPE_B )
2008-10-18 22:41:21 +00:00
presentation_delayed = 1 ;
2013-07-28 20:04:05 +03:00
if ( pkt -> pts != AV_NOPTS_VALUE && pkt -> dts != AV_NOPTS_VALUE &&
2021-02-02 17:29:23 +01:00
st -> pts_wrap_bits < 63 && pkt -> dts > INT64_MIN + ( 1LL << st -> pts_wrap_bits ) &&
2013-07-28 20:04:05 +03:00
pkt -> dts - ( 1LL << ( st -> pts_wrap_bits - 1 )) > pkt -> pts ) {
2021-06-05 11:12:03 -03:00
if ( is_relative ( st -> internal -> cur_dts ) || pkt -> dts - ( 1LL << ( st -> pts_wrap_bits - 1 )) > st -> internal -> cur_dts ) {
2014-01-26 23:35:38 +01:00
pkt -> dts -= 1LL << st -> pts_wrap_bits ;
2012-08-24 03:08:51 +02:00
} else
2014-01-26 23:35:38 +01:00
pkt -> pts += 1LL << st -> pts_wrap_bits ;
2007-07-31 15:06:27 +00:00
}
2014-01-16 01:53:03 +01:00
/* Some MPEG-2 in MPEG-PS lack dts (issue #171 / input_file.mpg).
* We take the conservative approach and discard both.
* Note: If this is misbehaving for an H.264 file, then possibly
* presentation_delayed is not set correctly. */
if ( delay == 1 && pkt -> dts == pkt -> pts &&
pkt -> dts != AV_NOPTS_VALUE && presentation_delayed ) {
2011-09-14 19:53:59 +02:00
av_log ( s , AV_LOG_DEBUG , "invalid dts/pts combination %" PRIi64 " \n " , pkt -> dts );
2013-12-15 04:17:05 +01:00
if ( strcmp ( s -> iformat -> name , "mov,mp4,m4a,3gp,3g2,mj2" )
&& strcmp ( s -> iformat -> name , "flv" )) // otherwise we discard correct timestamps for vc1-wmapro.ism
2014-01-26 23:35:38 +01:00
pkt -> dts = AV_NOPTS_VALUE ;
2008-10-19 01:02:48 +00:00
}
2014-01-26 23:35:38 +01:00
duration = av_mul_q (( AVRational ) { pkt -> duration , 1 }, st -> time_base );
2019-09-05 23:06:21 +02:00
if ( pkt -> duration <= 0 ) {
2014-10-08 19:23:14 +00:00
ff_compute_frame_duration ( s , & num , & den , st , pc , pkt );
2003-11-10 18:37:55 +00:00
if ( den && num ) {
2014-01-26 23:35:38 +01:00
duration = ( AVRational ) { num , den };
pkt -> duration = av_rescale_rnd ( 1 ,
num * ( int64_t ) st -> time_base . den ,
2014-01-16 01:53:03 +01:00
den * ( int64_t ) st -> time_base . num ,
AV_ROUND_DOWN );
2003-11-10 18:37:55 +00:00
}
}
2014-01-03 17:44:15 +01:00
2019-09-05 23:06:21 +02:00
if ( pkt -> duration > 0 && ( s -> internal -> packet_buffer || s -> internal -> parse_queue ))
2012-03-06 03:56:25 +01:00
update_initial_durations ( s , st , pkt -> stream_index , pkt -> duration );
2003-11-10 18:37:55 +00:00
2014-01-16 01:53:03 +01:00
/* Correct timestamps with byte offset if demuxers only have timestamps
* on packet boundaries */
2021-05-01 23:28:18 -03:00
if ( pc && st -> internal -> need_parsing == AVSTREAM_PARSE_TIMESTAMPS && pkt -> size ) {
2007-04-13 07:50:04 +00:00
/* this will estimate bitrate based on this frame's duration and size */
offset = av_rescale ( pc -> offset , pkt -> duration , pkt -> size );
2014-01-16 01:53:03 +01:00
if ( pkt -> pts != AV_NOPTS_VALUE )
2007-04-13 07:50:04 +00:00
pkt -> pts += offset ;
2014-01-16 01:53:03 +01:00
if ( pkt -> dts != AV_NOPTS_VALUE )
2007-04-13 07:50:04 +00:00
pkt -> dts += offset ;
}
2007-06-12 09:29:25 +00:00
/* This may be redundant, but it should not hurt. */
2014-01-16 01:53:03 +01:00
if ( pkt -> dts != AV_NOPTS_VALUE &&
pkt -> pts != AV_NOPTS_VALUE &&
pkt -> pts > pkt -> dts )
2007-03-17 14:29:00 +00:00
presentation_delayed = 1 ;
2005-12-17 18:14:38 +00:00
2015-04-20 17:03:27 +02:00
if ( s -> debug & FF_FDEBUG_TS )
2018-08-13 12:32:41 +05:30
av_log ( s , AV_LOG_DEBUG ,
2015-09-29 15:14:59 +02:00
"IN delayed:%d pts:%s, dts:%s cur_dts:%s st:%d pc:%p duration:%" PRId64 " delay:%d onein_oneout:%d \n " ,
2021-06-05 11:12:03 -03:00
presentation_delayed , av_ts2str ( pkt -> pts ), av_ts2str ( pkt -> dts ), av_ts2str ( st -> internal -> cur_dts ),
2014-10-13 23:45:52 +02:00
pkt -> stream_index , pc , pkt -> duration , delay , onein_oneout );
2015-04-20 17:03:27 +02:00
2014-01-26 23:35:38 +01:00
/* Interpolate PTS and DTS if they are not present. We skip H264
2014-01-16 01:53:03 +01:00
* currently because delay and has_b_frames are not reliably set. */
if (( delay == 0 || ( delay == 1 && pc )) &&
2014-02-22 12:21:28 +01:00
onein_oneout ) {
2007-03-17 14:29:00 +00:00
if ( presentation_delayed ) {
2008-01-16 22:14:26 +00:00
/* DTS = decompression timestamp */
/* PTS = presentation timestamp */
2007-03-17 14:29:00 +00:00
if ( pkt -> dts == AV_NOPTS_VALUE )
2021-05-01 23:05:21 -03:00
pkt -> dts = st -> internal -> last_IP_pts ;
2012-12-02 19:27:21 +01:00
update_initial_timestamps ( s , pkt -> stream_index , pkt -> dts , pkt -> pts , pkt );
2007-03-17 14:29:00 +00:00
if ( pkt -> dts == AV_NOPTS_VALUE )
2021-06-05 11:12:03 -03:00
pkt -> dts = st -> internal -> cur_dts ;
2007-03-17 02:03:59 +00:00
2014-01-16 01:53:03 +01:00
/* This is tricky: the dts must be incremented by the duration
* of the frame we are displaying, i.e. the last I- or P-frame. */
2021-05-01 23:05:21 -03:00
if ( st -> internal -> last_IP_duration == 0 && ( uint64_t ) pkt -> duration <= INT32_MAX )
st -> internal -> last_IP_duration = pkt -> duration ;
2014-01-16 01:53:03 +01:00
if ( pkt -> dts != AV_NOPTS_VALUE )
2021-06-05 11:12:03 -03:00
st -> internal -> cur_dts = av_sat_add64 ( pkt -> dts , st -> internal -> last_IP_duration );
2014-12-09 03:34:20 +01:00
if ( pkt -> dts != AV_NOPTS_VALUE &&
pkt -> pts == AV_NOPTS_VALUE &&
2021-05-01 23:05:21 -03:00
st -> internal -> last_IP_duration > 0 &&
2021-06-05 11:12:03 -03:00
(( uint64_t ) st -> internal -> cur_dts - ( uint64_t ) next_dts + 1 ) <= 2 &&
2014-12-09 03:34:20 +01:00
next_dts != next_pts &&
next_pts != AV_NOPTS_VALUE )
pkt -> pts = next_dts ;
2018-10-12 20:55:25 +02:00
if (( uint64_t ) pkt -> duration <= INT32_MAX )
2021-05-01 23:05:21 -03:00
st -> internal -> last_IP_duration = pkt -> duration ;
st -> internal -> last_IP_pts = pkt -> pts ;
2014-01-16 01:53:03 +01:00
/* Cannot compute PTS if not present (we can compute it only
* by knowing the future. */
2012-02-27 18:07:07 -05:00
} else if ( pkt -> pts != AV_NOPTS_VALUE ||
pkt -> dts != AV_NOPTS_VALUE ||
2019-09-05 23:06:21 +02:00
pkt -> duration > 0 ) {
2012-02-27 18:07:07 -05:00
2007-03-17 14:29:00 +00:00
/* presentation is not delayed : PTS and DTS are the same */
2012-05-05 00:44:48 +02:00
if ( pkt -> pts == AV_NOPTS_VALUE )
2007-03-17 14:29:00 +00:00
pkt -> pts = pkt -> dts ;
2012-05-05 00:44:48 +02:00
update_initial_timestamps ( s , pkt -> stream_index , pkt -> pts ,
2012-12-02 19:27:21 +01:00
pkt -> pts , pkt );
2012-05-05 00:44:48 +02:00
if ( pkt -> pts == AV_NOPTS_VALUE )
2021-06-05 11:12:03 -03:00
pkt -> pts = st -> internal -> cur_dts ;
2007-03-17 14:29:00 +00:00
pkt -> dts = pkt -> pts ;
2019-09-05 23:06:21 +02:00
if ( pkt -> pts != AV_NOPTS_VALUE && duration . num >= 0 )
2021-06-05 11:12:03 -03:00
st -> internal -> cur_dts = av_add_stable ( st -> time_base , pkt -> pts , duration , 1 );
2007-03-17 14:29:00 +00:00
}
2003-11-10 18:37:55 +00:00
}
2007-03-17 14:27:01 +00:00
2016-03-08 02:42:10 +01:00
if ( pkt -> pts != AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY ) {
2020-10-09 09:22:36 +02:00
st -> internal -> pts_buffer [ 0 ] = pkt -> pts ;
for ( i = 0 ; i < delay && st -> internal -> pts_buffer [ i ] > st -> internal -> pts_buffer [ i + 1 ]; i ++ )
FFSWAP ( int64_t , st -> internal -> pts_buffer [ i ], st -> internal -> pts_buffer [ i + 1 ]);
2014-02-22 13:04:18 +01:00
2016-03-08 02:42:10 +01:00
if ( has_decode_delay_been_guessed ( st ))
2020-10-09 09:22:36 +02:00
pkt -> dts = select_from_pts_buffer ( st , st -> internal -> pts_buffer , pkt -> dts );
2007-03-17 14:27:01 +00:00
}
2014-01-26 23:35:38 +01:00
// We skipped it above so we try here.
2014-02-22 12:21:28 +01:00
if ( ! onein_oneout )
2014-01-26 23:35:38 +01:00
// This should happen on the first packet
update_initial_timestamps ( s , pkt -> stream_index , pkt -> dts , pkt -> pts , pkt );
2021-06-05 11:12:03 -03:00
if ( pkt -> dts > st -> internal -> cur_dts )
st -> internal -> cur_dts = pkt -> dts ;
2007-03-17 14:27:01 +00:00
2015-04-20 17:03:27 +02:00
if ( s -> debug & FF_FDEBUG_TS )
2019-04-19 08:58:37 +01:00
av_log ( s , AV_LOG_DEBUG , "OUTdelayed:%d/%d pts:%s, dts:%s cur_dts:%s st:%d (%d) \n " ,
2021-06-05 11:12:03 -03:00
presentation_delayed , delay , av_ts2str ( pkt -> pts ), av_ts2str ( pkt -> dts ), av_ts2str ( st -> internal -> cur_dts ), st -> index , st -> id );
2005-12-17 18:14:38 +00:00
2003-11-10 18:37:55 +00:00
/* update flags */
2020-04-21 23:35:23 +08:00
if ( st -> codecpar -> codec_type == AVMEDIA_TYPE_DATA || ff_is_intra_only ( st -> codecpar -> codec_id ))
2010-03-31 12:29:58 +00:00
pkt -> flags |= AV_PKT_FLAG_KEY ;
2003-11-10 18:37:55 +00:00
}
2012-03-04 15:49:26 +01:00
/**
2014-01-16 01:53:03 +01:00
* Parse a packet, add all split parts to parse_queue.
2012-03-04 15:49:26 +01:00
*
2019-09-20 22:39:15 +02:00
* @param pkt Packet to parse; must not be NULL.
* @param flush Indicates whether to flush. If set, pkt must be blank.
2012-03-04 15:49:26 +01:00
*/
2019-09-20 22:39:15 +02:00
static int parse_packet ( AVFormatContext * s , AVPacket * pkt ,
int stream_index , int flush )
2012-03-04 15:49:26 +01:00
{
2021-01-31 13:05:49 -03:00
AVPacket * out_pkt = s -> internal -> parse_pkt ;
2014-01-16 01:53:03 +01:00
AVStream * st = s -> streams [ stream_index ];
2019-09-20 22:39:15 +02:00
uint8_t * data = pkt -> data ;
int size = pkt -> size ;
int ret = 0 , got_output = flush ;
2012-03-04 15:49:26 +01:00
2021-05-01 23:28:18 -03:00
if ( ! size && ! flush && st -> internal -> parser -> flags & PARSER_FLAG_COMPLETE_FRAMES ) {
2012-03-25 13:16:48 +02:00
// preserve 0-size sync packets
2021-05-01 23:28:18 -03:00
compute_pkt_fields ( s , st , st -> internal -> parser , pkt , AV_NOPTS_VALUE , AV_NOPTS_VALUE );
2012-03-04 15:49:26 +01:00
}
2019-09-20 22:39:15 +02:00
while ( size > 0 || ( flush && got_output )) {
2012-03-04 15:49:26 +01:00
int len ;
2014-12-09 03:33:44 +01:00
int64_t next_pts = pkt -> pts ;
int64_t next_dts = pkt -> dts ;
2012-03-04 15:49:26 +01:00
2021-05-01 23:28:18 -03:00
len = av_parser_parse2 ( st -> internal -> parser , st -> internal -> avctx ,
2021-01-31 13:05:49 -03:00
& out_pkt -> data , & out_pkt -> size , data , size ,
2012-03-04 15:49:26 +01:00
pkt -> pts , pkt -> dts , pkt -> pos );
pkt -> pts = pkt -> dts = AV_NOPTS_VALUE ;
2012-07-24 17:29:47 +02:00
pkt -> pos = - 1 ;
2012-03-04 15:49:26 +01:00
/* increment read pointer */
2021-02-14 23:55:39 +01:00
av_assert1 ( data || ! len );
2021-02-14 22:24:46 +01:00
data = len ? data + len : data ;
2012-03-04 15:49:26 +01:00
size -= len ;
2021-01-31 13:05:49 -03:00
got_output = !! out_pkt -> size ;
2012-03-04 15:49:26 +01:00
2021-01-31 13:05:49 -03:00
if ( ! out_pkt -> size )
2012-03-04 15:49:26 +01:00
continue ;
2021-01-31 13:05:49 -03:00
if ( pkt -> buf && out_pkt -> data == pkt -> data ) {
/* reference pkt->buf only when out_pkt->data is guaranteed to point
2018-04-12 00:06:30 -03:00
* to data in it and not in the parser's internal buffer. */
2021-05-01 23:28:18 -03:00
/* XXX: Ensure this is the case with all parsers when st->internal->parser->flags
2018-04-12 00:06:30 -03:00
* is PARSER_FLAG_COMPLETE_FRAMES and check for that instead? */
2021-01-31 13:05:49 -03:00
out_pkt -> buf = av_buffer_ref ( pkt -> buf );
if ( ! out_pkt -> buf ) {
2018-04-12 00:06:30 -03:00
ret = AVERROR ( ENOMEM );
goto fail ;
}
} else {
2021-01-31 13:05:49 -03:00
ret = av_packet_make_refcounted ( out_pkt );
2018-04-12 00:06:30 -03:00
if ( ret < 0 )
goto fail ;
}
2013-05-17 07:39:34 +02:00
if ( pkt -> side_data ) {
2021-01-31 13:05:49 -03:00
out_pkt -> side_data = pkt -> side_data ;
out_pkt -> side_data_elems = pkt -> side_data_elems ;
2014-01-16 01:53:03 +01:00
pkt -> side_data = NULL ;
pkt -> side_data_elems = 0 ;
2013-05-17 07:39:34 +02:00
}
2012-03-04 15:49:26 +01:00
/* set the duration */
2021-05-01 23:28:18 -03:00
out_pkt -> duration = ( st -> internal -> parser -> flags & PARSER_FLAG_COMPLETE_FRAMES ) ? pkt -> duration : 0 ;
2014-06-18 20:42:52 +02:00
if ( st -> codecpar -> codec_type == AVMEDIA_TYPE_AUDIO ) {
if ( st -> internal -> avctx -> sample_rate > 0 ) {
2021-01-31 13:05:49 -03:00
out_pkt -> duration =
2021-05-01 23:28:18 -03:00
av_rescale_q_rnd ( st -> internal -> parser -> duration ,
2014-06-18 20:42:52 +02:00
( AVRational ) { 1 , st -> internal -> avctx -> sample_rate },
2014-01-16 01:53:03 +01:00
st -> time_base ,
AV_ROUND_DOWN );
2012-03-04 15:49:26 +01:00
}
}
2021-01-31 13:05:49 -03:00
out_pkt -> stream_index = st -> index ;
2021-05-01 23:28:18 -03:00
out_pkt -> pts = st -> internal -> parser -> pts ;
out_pkt -> dts = st -> internal -> parser -> dts ;
out_pkt -> pos = st -> internal -> parser -> pos ;
2021-01-31 13:05:49 -03:00
out_pkt -> flags |= pkt -> flags & AV_PKT_FLAG_DISCARD ;
2012-07-24 17:34:13 +02:00
2021-05-01 23:28:18 -03:00
if ( st -> internal -> need_parsing == AVSTREAM_PARSE_FULL_RAW )
out_pkt -> pos = st -> internal -> parser -> frame_offset ;
2012-03-04 15:49:26 +01:00
2021-05-01 23:28:18 -03:00
if ( st -> internal -> parser -> key_frame == 1 ||
( st -> internal -> parser -> key_frame == - 1 &&
st -> internal -> parser -> pict_type == AV_PICTURE_TYPE_I ))
2021-01-31 13:05:49 -03:00
out_pkt -> flags |= AV_PKT_FLAG_KEY ;
2012-03-04 15:49:26 +01:00
2021-05-01 23:28:18 -03:00
if ( st -> internal -> parser -> key_frame == - 1 && st -> internal -> parser -> pict_type == AV_PICTURE_TYPE_NONE && ( pkt -> flags & AV_PKT_FLAG_KEY ))
2021-01-31 13:05:49 -03:00
out_pkt -> flags |= AV_PKT_FLAG_KEY ;
2012-06-02 21:11:43 +02:00
2021-05-01 23:28:18 -03:00
compute_pkt_fields ( s , st , st -> internal -> parser , out_pkt , next_dts , next_pts );
2012-03-04 15:49:26 +01:00
2020-08-17 12:03:50 -03:00
ret = avpriv_packet_list_put ( & s -> internal -> parse_queue ,
2018-03-27 19:48:18 -03:00
& s -> internal -> parse_queue_end ,
2021-01-31 13:05:49 -03:00
out_pkt , NULL , 0 );
2021-03-18 04:59:54 +01:00
if ( ret < 0 )
2012-03-04 15:49:26 +01:00
goto fail ;
}
/* end of the stream => close and free the parser */
2019-09-20 22:39:15 +02:00
if ( flush ) {
2021-05-01 23:28:18 -03:00
av_parser_close ( st -> internal -> parser );
st -> internal -> parser = NULL ;
2012-03-04 15:49:26 +01:00
}
fail :
2021-03-18 04:59:54 +01:00
if ( ret < 0 )
av_packet_unref ( out_pkt );
2015-10-23 11:11:31 +02:00
av_packet_unref ( pkt );
2012-03-04 15:49:26 +01:00
return ret ;
}
2014-09-20 13:48:05 +02:00
static int64_t ts_to_samples ( AVStream * st , int64_t ts )
{
2016-04-10 20:58:15 +01:00
return av_rescale ( ts , st -> time_base . num * st -> codecpar -> sample_rate , st -> time_base . den );
2014-09-20 13:48:05 +02:00
}
2011-07-15 20:27:43 +02:00
static int read_frame_internal ( AVFormatContext * s , AVPacket * pkt )
2003-11-10 18:37:55 +00:00
{
2019-09-20 22:39:16 +02:00
int ret , i , got_packet = 0 ;
2014-07-31 19:56:37 -04:00
AVDictionary * metadata = NULL ;
2003-11-10 18:37:55 +00:00
2015-02-06 14:53:40 +01:00
while ( ! got_packet && ! s -> internal -> parse_queue ) {
2012-03-04 15:49:26 +01:00
AVStream * st ;
2005-12-17 18:14:38 +00:00
2012-03-04 15:49:26 +01:00
/* read next packet */
2019-09-20 22:39:14 +02:00
ret = ff_read_packet ( s , pkt );
2012-03-04 15:49:26 +01:00
if ( ret < 0 ) {
if ( ret == AVERROR ( EAGAIN ))
2003-11-10 18:37:55 +00:00
return ret ;
2012-03-04 15:49:26 +01:00
/* flush the parsers */
2014-01-16 01:53:03 +01:00
for ( i = 0 ; i < s -> nb_streams ; i ++ ) {
2012-03-04 15:49:26 +01:00
st = s -> streams [ i ];
2021-05-01 23:28:18 -03:00
if ( st -> internal -> parser && st -> internal -> need_parsing )
2019-09-20 22:39:15 +02:00
parse_packet ( s , pkt , st -> index , 1 );
2003-12-15 14:45:37 +00:00
}
2012-03-04 15:49:26 +01:00
/* all remaining packets are now in parse_queue =>
* really terminate parsing */
break ;
}
ret = 0 ;
2019-09-20 22:39:14 +02:00
st = s -> streams [ pkt -> stream_index ];
2005-12-17 18:14:38 +00:00
2020-10-25 15:50:30 +01:00
st -> event_flags |= AVSTREAM_EVENT_FLAG_NEW_PACKETS ;
2016-04-10 20:58:15 +01:00
/* update context if required */
if ( st -> internal -> need_context_update ) {
if ( avcodec_is_open ( st -> internal -> avctx )) {
av_log ( s , AV_LOG_DEBUG , "Demuxer context update while decoder is open, closing and trying to re-open \n " );
avcodec_close ( st -> internal -> avctx );
2020-10-09 08:15:27 +02:00
st -> internal -> info -> found_decoder = 0 ;
2016-04-10 20:58:15 +01:00
}
2016-10-17 20:26:51 +02:00
/* close parser, because it depends on the codec */
2021-05-01 23:28:18 -03:00
if ( st -> internal -> parser && st -> internal -> avctx -> codec_id != st -> codecpar -> codec_id ) {
av_parser_close ( st -> internal -> parser );
st -> internal -> parser = NULL ;
2016-10-17 20:26:51 +02:00
}
2016-04-10 20:58:15 +01:00
ret = avcodec_parameters_to_context ( st -> internal -> avctx , st -> codecpar );
2019-09-24 18:31:44 +02:00
if ( ret < 0 ) {
2019-09-20 22:39:14 +02:00
av_packet_unref ( pkt );
2016-04-10 20:58:15 +01:00
return ret ;
2019-09-24 18:31:44 +02:00
}
2016-04-10 20:58:15 +01:00
st -> internal -> need_context_update = 0 ;
}
2019-09-20 22:39:14 +02:00
if ( pkt -> pts != AV_NOPTS_VALUE &&
pkt -> dts != AV_NOPTS_VALUE &&
pkt -> pts < pkt -> dts ) {
2014-01-16 01:53:03 +01:00
av_log ( s , AV_LOG_WARNING ,
2014-01-26 23:35:38 +01:00
"Invalid timestamps stream=%d, pts=%s, dts=%s, size=%d \n " ,
2019-09-20 22:39:14 +02:00
pkt -> stream_index ,
av_ts2str ( pkt -> pts ),
av_ts2str ( pkt -> dts ),
pkt -> size );
2012-03-04 15:49:26 +01:00
}
if ( s -> debug & FF_FDEBUG_TS )
2014-01-16 01:53:03 +01:00
av_log ( s , AV_LOG_DEBUG ,
2015-09-29 15:14:59 +02:00
"ff_read_packet stream=%d, pts=%s, dts=%s, size=%d, duration=%" PRId64 ", flags=%d \n " ,
2019-09-20 22:39:14 +02:00
pkt -> stream_index ,
av_ts2str ( pkt -> pts ),
av_ts2str ( pkt -> dts ),
pkt -> size , pkt -> duration , pkt -> flags );
2008-05-23 17:52:42 +00:00
2021-05-01 23:28:18 -03:00
if ( st -> internal -> need_parsing && ! st -> internal -> parser && ! ( s -> flags & AVFMT_FLAG_NOPARSE )) {
st -> internal -> parser = av_parser_init ( st -> codecpar -> codec_id );
if ( ! st -> internal -> parser ) {
2012-03-06 03:56:25 +01:00
av_log ( s , AV_LOG_VERBOSE , "parser not found for codec "
"%s, packets or times may be invalid. \n " ,
2016-04-10 20:58:15 +01:00
avcodec_get_name ( st -> codecpar -> codec_id ));
2012-03-04 15:49:26 +01:00
/* no parser available: just output the raw packets */
2021-05-01 23:28:18 -03:00
st -> internal -> need_parsing = AVSTREAM_PARSE_NONE ;
} else if ( st -> internal -> need_parsing == AVSTREAM_PARSE_HEADERS )
st -> internal -> parser -> flags |= PARSER_FLAG_COMPLETE_FRAMES ;
else if ( st -> internal -> need_parsing == AVSTREAM_PARSE_FULL_ONCE )
st -> internal -> parser -> flags |= PARSER_FLAG_ONCE ;
else if ( st -> internal -> need_parsing == AVSTREAM_PARSE_FULL_RAW )
st -> internal -> parser -> flags |= PARSER_FLAG_USE_CODEC_TS ;
2003-11-10 18:37:55 +00:00
}
2012-03-04 15:49:26 +01:00
2021-05-01 23:28:18 -03:00
if ( ! st -> internal -> need_parsing || ! st -> internal -> parser ) {
2012-03-04 15:49:26 +01:00
/* no parsing needed: we just output the packet as is */
2014-12-09 03:33:44 +01:00
compute_pkt_fields ( s , st , NULL , pkt , AV_NOPTS_VALUE , AV_NOPTS_VALUE );
2012-03-04 15:49:26 +01:00
if (( s -> iformat -> flags & AVFMT_GENERIC_INDEX ) &&
( pkt -> flags & AV_PKT_FLAG_KEY ) && pkt -> dts != AV_NOPTS_VALUE ) {
ff_reduce_index ( s , st -> index );
2014-01-16 01:53:03 +01:00
av_add_index_entry ( st , pkt -> pos , pkt -> dts ,
0 , 0 , AVINDEX_KEYFRAME );
2012-03-04 15:49:26 +01:00
}
got_packet = 1 ;
} else if ( st -> discard < AVDISCARD_ALL ) {
2019-09-20 22:39:15 +02:00
if (( ret = parse_packet ( s , pkt , pkt -> stream_index , 0 )) < 0 )
2012-03-04 15:49:26 +01:00
return ret ;
2016-04-10 20:58:15 +01:00
st -> codecpar -> sample_rate = st -> internal -> avctx -> sample_rate ;
st -> codecpar -> bit_rate = st -> internal -> avctx -> bit_rate ;
st -> codecpar -> channels = st -> internal -> avctx -> channels ;
st -> codecpar -> channel_layout = st -> internal -> avctx -> channel_layout ;
st -> codecpar -> codec_id = st -> internal -> avctx -> codec_id ;
2012-03-04 15:49:26 +01:00
} else {
/* free packet */
2019-09-20 22:39:14 +02:00
av_packet_unref ( pkt );
2012-03-04 15:49:26 +01:00
}
2012-04-14 00:17:30 +02:00
if ( pkt -> flags & AV_PKT_FLAG_KEY )
2020-10-09 09:22:36 +02:00
st -> internal -> skip_to_keyframe = 0 ;
if ( st -> internal -> skip_to_keyframe ) {
2019-09-20 22:39:14 +02:00
av_packet_unref ( pkt );
2012-04-14 00:17:30 +02:00
got_packet = 0 ;
}
2003-11-10 18:37:55 +00:00
}
2012-03-04 15:49:26 +01:00
2015-02-06 14:53:40 +01:00
if ( ! got_packet && s -> internal -> parse_queue )
2020-08-17 12:03:50 -03:00
ret = avpriv_packet_list_get ( & s -> internal -> parse_queue , & s -> internal -> parse_queue_end , pkt );
2012-03-04 15:49:26 +01:00
2013-11-21 00:15:05 +01:00
if ( ret >= 0 ) {
AVStream * st = s -> streams [ pkt -> stream_index ];
2014-09-20 13:48:05 +02:00
int discard_padding = 0 ;
2020-10-09 09:22:36 +02:00
if ( st -> internal -> first_discard_sample && pkt -> pts != AV_NOPTS_VALUE ) {
2014-09-20 13:48:05 +02:00
int64_t pts = pkt -> pts - ( is_relative ( pkt -> pts ) ? RELATIVE_TS_BASE : 0 );
int64_t sample = ts_to_samples ( st , pts );
int duration = ts_to_samples ( st , pkt -> duration );
int64_t end_sample = sample + duration ;
2020-10-09 09:22:36 +02:00
if ( duration > 0 && end_sample >= st -> internal -> first_discard_sample &&
sample < st -> internal -> last_discard_sample )
discard_padding = FFMIN ( end_sample - st -> internal -> first_discard_sample , duration );
2014-09-20 13:48:05 +02:00
}
2020-10-09 09:22:36 +02:00
if ( st -> internal -> start_skip_samples && ( pkt -> pts == 0 || pkt -> pts == RELATIVE_TS_BASE ))
st -> internal -> skip_samples = st -> internal -> start_skip_samples ;
if ( st -> internal -> skip_samples || discard_padding ) {
2013-11-21 00:15:05 +01:00
uint8_t * p = av_packet_new_side_data ( pkt , AV_PKT_DATA_SKIP_SAMPLES , 10 );
if ( p ) {
2020-10-09 09:22:36 +02:00
AV_WL32 ( p , st -> internal -> skip_samples );
2014-09-20 13:48:05 +02:00
AV_WL32 ( p + 4 , discard_padding );
2020-10-09 09:22:36 +02:00
av_log ( s , AV_LOG_DEBUG , "demuxer injecting skip %d / discard %d \n " , st -> internal -> skip_samples , discard_padding );
2013-11-21 00:15:05 +01:00
}
2020-10-09 09:22:36 +02:00
st -> internal -> skip_samples = 0 ;
2013-11-21 00:15:05 +01:00
}
2014-04-13 17:57:43 +02:00
2020-10-09 09:22:36 +02:00
if ( st -> internal -> inject_global_side_data ) {
2014-04-13 17:57:43 +02:00
for ( i = 0 ; i < st -> nb_side_data ; i ++ ) {
AVPacketSideData * src_sd = & st -> side_data [ i ];
uint8_t * dst_data ;
if ( av_packet_get_side_data ( pkt , src_sd -> type , NULL ))
continue ;
dst_data = av_packet_new_side_data ( pkt , src_sd -> type , src_sd -> size );
if ( ! dst_data ) {
2014-04-15 13:35:46 +02:00
av_log ( s , AV_LOG_WARNING , "Could not inject global side data \n " );
2014-04-13 17:57:43 +02:00
continue ;
}
memcpy ( dst_data , src_sd -> data , src_sd -> size );
}
2020-10-09 09:22:36 +02:00
st -> internal -> inject_global_side_data = 0 ;
2014-04-13 17:57:43 +02:00
}
2014-04-13 18:02:42 +02:00
}
2013-11-21 00:09:29 +01:00
2014-07-31 19:56:37 -04:00
av_opt_get_dict_val ( s , "metadata" , AV_OPT_SEARCH_CHILDREN , & metadata );
if ( metadata ) {
s -> event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED ;
av_dict_copy ( & s -> metadata , metadata , 0 );
av_dict_free ( & metadata );
av_opt_set_dict_val ( s , "metadata" , NULL , AV_OPT_SEARCH_CHILDREN );
}
2014-01-16 01:53:03 +01:00
if ( s -> debug & FF_FDEBUG_TS )
av_log ( s , AV_LOG_DEBUG ,
2014-01-26 23:35:38 +01:00
"read_frame_internal stream=%d, pts=%s, dts=%s, "
2015-09-26 18:13:55 +02:00
"size=%d, duration=%" PRId64 ", flags=%d \n " ,
2014-01-26 23:35:38 +01:00
pkt -> stream_index ,
av_ts2str ( pkt -> pts ),
av_ts2str ( pkt -> dts ),
2014-01-16 01:53:03 +01:00
pkt -> size , pkt -> duration , pkt -> flags );
2006-08-08 19:55:32 +00:00
2019-08-24 22:00:12 +02:00
/* A demuxer might have returned EOF because of an IO error, let's
* propagate this back to the user. */
if ( ret == AVERROR_EOF && s -> pb && s -> pb -> error < 0 && s -> pb -> error != AVERROR ( EAGAIN ))
ret = s -> pb -> error ;
2012-03-04 15:49:26 +01:00
return ret ;
2012-01-05 10:14:07 +01:00
}
2003-11-10 18:37:55 +00:00
int av_read_frame ( AVFormatContext * s , AVPacket * pkt )
2001-07-22 14:18:56 +00:00
{
2012-01-05 10:16:41 +01:00
const int genpts = s -> flags & AVFMT_FLAG_GENPTS ;
2014-01-16 01:53:03 +01:00
int eof = 0 ;
2012-03-07 22:13:39 +01:00
int ret ;
2012-07-24 17:33:15 +02:00
AVStream * st ;
2001-07-22 14:18:56 +00:00
2012-03-07 22:13:39 +01:00
if ( ! genpts ) {
2015-02-11 02:13:46 +01:00
ret = s -> internal -> packet_buffer
2020-08-17 12:03:50 -03:00
? avpriv_packet_list_get ( & s -> internal -> packet_buffer ,
2015-02-11 02:13:46 +01:00
& s -> internal -> packet_buffer_end , pkt )
2014-01-26 23:35:38 +01:00
: read_frame_internal ( s , pkt );
2012-09-24 20:38:14 +02:00
if ( ret < 0 )
return ret ;
goto return_packet ;
2012-03-07 22:13:39 +01:00
}
2012-01-05 10:14:07 +01:00
2012-01-05 10:16:41 +01:00
for (;;) {
2021-03-05 11:26:24 -03:00
PacketList * pktl = s -> internal -> packet_buffer ;
2001-07-22 14:18:56 +00:00
2005-08-15 14:22:43 +00:00
if ( pktl ) {
2012-01-05 10:16:41 +01:00
AVPacket * next_pkt = & pktl -> pkt ;
2005-08-15 14:22:43 +00:00
2012-01-05 10:14:07 +01:00
if ( next_pkt -> dts != AV_NOPTS_VALUE ) {
2010-06-22 08:48:28 +00:00
int wrap_bits = s -> streams [ next_pkt -> stream_index ] -> pts_wrap_bits ;
2012-04-04 12:01:04 -07:00
// last dts seen for this stream. if any of packets following
// current one had no dts, we will set this to AV_NOPTS_VALUE.
int64_t last_dts = next_pkt -> dts ;
2017-11-24 17:46:16 -03:00
av_assert2 ( wrap_bits <= 64 );
2012-01-05 10:16:41 +01:00
while ( pktl && next_pkt -> pts == AV_NOPTS_VALUE ) {
if ( pktl -> pkt . stream_index == next_pkt -> stream_index &&
2017-11-17 13:35:56 -08:00
av_compare_mod ( next_pkt -> dts , pktl -> pkt . dts , 2ULL << ( wrap_bits - 1 )) < 0 ) {
if ( av_compare_mod ( pktl -> pkt . pts , pktl -> pkt . dts , 2ULL << ( wrap_bits - 1 ))) {
2014-01-26 23:35:38 +01:00
// not B-frame
2012-04-04 12:01:04 -07:00
next_pkt -> pts = pktl -> pkt . dts ;
}
if ( last_dts != AV_NOPTS_VALUE ) {
// Once last dts was set to AV_NOPTS_VALUE, we don't change it.
last_dts = pktl -> pkt . dts ;
}
2005-08-15 14:22:43 +00:00
}
2012-01-05 10:16:41 +01:00
pktl = pktl -> next ;
2005-08-15 14:22:43 +00:00
}
2012-04-04 12:01:04 -07:00
if ( eof && next_pkt -> pts == AV_NOPTS_VALUE && last_dts != AV_NOPTS_VALUE ) {
// Fixing the last reference frame had none pts issue (For MXF etc).
// We only do this when
// 1. eof.
// 2. we are not able to resolve a pts value for current packet.
// 3. the packets for this stream at the end of the files had valid dts.
next_pkt -> pts = last_dts + next_pkt -> duration ;
}
2015-02-06 14:53:40 +01:00
pktl = s -> internal -> packet_buffer ;
2005-08-15 14:22:43 +00:00
}
2005-12-17 18:14:38 +00:00
2012-01-05 10:14:07 +01:00
/* read packet from packet buffer, if there is data */
2014-07-13 01:07:59 +02:00
st = s -> streams [ next_pkt -> stream_index ];
if ( ! ( next_pkt -> pts == AV_NOPTS_VALUE && st -> discard < AVDISCARD_ALL &&
2012-03-07 22:13:39 +01:00
next_pkt -> dts != AV_NOPTS_VALUE && ! eof )) {
2020-08-17 12:03:50 -03:00
ret = avpriv_packet_list_get ( & s -> internal -> packet_buffer ,
2015-02-06 14:53:40 +01:00
& s -> internal -> packet_buffer_end , pkt );
2012-03-07 22:13:39 +01:00
goto return_packet ;
}
2005-08-15 14:22:43 +00:00
}
2005-12-17 18:14:38 +00:00
2012-01-05 10:14:07 +01:00
ret = read_frame_internal ( s , pkt );
if ( ret < 0 ) {
if ( pktl && ret != AVERROR ( EAGAIN )) {
eof = 1 ;
continue ;
} else
return ret ;
2005-08-15 14:22:43 +00:00
}
2012-01-05 10:14:07 +01:00
2020-08-17 12:03:50 -03:00
ret = avpriv_packet_list_put ( & s -> internal -> packet_buffer ,
2018-03-27 19:48:18 -03:00
& s -> internal -> packet_buffer_end ,
2020-08-17 12:03:50 -03:00
pkt , NULL , 0 );
2019-09-28 04:42:24 +02:00
if ( ret < 0 ) {
av_packet_unref ( pkt );
2015-10-23 11:11:32 +02:00
return ret ;
2019-09-28 04:42:24 +02:00
}
2001-07-22 14:18:56 +00:00
}
2012-03-07 22:13:39 +01:00
return_packet :
2012-07-04 22:00:50 +02:00
2012-07-24 17:33:15 +02:00
st = s -> streams [ pkt -> stream_index ];
2012-07-24 18:00:11 +02:00
if (( s -> iformat -> flags & AVFMT_GENERIC_INDEX ) && pkt -> flags & AV_PKT_FLAG_KEY ) {
ff_reduce_index ( s , st -> index );
av_add_index_entry ( st , pkt -> pos , pkt -> dts , 0 , 0 , AVINDEX_KEYFRAME );
}
2012-03-07 22:13:39 +01:00
if ( is_relative ( pkt -> dts ))
pkt -> dts -= RELATIVE_TS_BASE ;
if ( is_relative ( pkt -> pts ))
pkt -> pts -= RELATIVE_TS_BASE ;
2012-07-24 18:00:11 +02:00
2012-03-07 22:13:39 +01:00
return ret ;
2001-07-22 14:18:56 +00:00
}
2003-11-10 18:37:55 +00:00
/* XXX: suppress the packet queue */
static void flush_packet_queue ( AVFormatContext * s )
{
2015-02-11 02:13:46 +01:00
if ( ! s -> internal )
return ;
2020-08-17 12:03:50 -03:00
avpriv_packet_list_free ( & s -> internal -> parse_queue , & s -> internal -> parse_queue_end );
avpriv_packet_list_free ( & s -> internal -> packet_buffer , & s -> internal -> packet_buffer_end );
avpriv_packet_list_free ( & s -> internal -> raw_packet_buffer , & s -> internal -> raw_packet_buffer_end );
2003-11-10 18:37:55 +00:00
2015-02-06 14:53:40 +01:00
s -> internal -> raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE ;
2003-11-10 18:37:55 +00:00
}
/*******************************************************/
/* seek support */
2004-01-13 22:02:49 +00:00
int av_find_default_stream_index ( AVFormatContext * s )
{
int i ;
AVStream * st ;
2014-08-01 22:17:52 +02:00
int best_stream = 0 ;
2015-07-01 22:35:07 +02:00
int best_score = INT_MIN ;
2004-01-13 22:02:49 +00:00
if ( s -> nb_streams <= 0 )
return - 1 ;
2014-01-16 01:53:03 +01:00
for ( i = 0 ; i < s -> nb_streams ; i ++ ) {
2014-08-01 22:17:52 +02:00
int score = 0 ;
2004-01-13 22:02:49 +00:00
st = s -> streams [ i ];
2016-04-10 20:58:15 +01:00
if ( st -> codecpar -> codec_type == AVMEDIA_TYPE_VIDEO ) {
2015-07-01 22:35:07 +02:00
if ( st -> disposition & AV_DISPOSITION_ATTACHED_PIC )
score -= 400 ;
2016-04-10 20:58:15 +01:00
if ( st -> codecpar -> width && st -> codecpar -> height )
2015-07-01 22:35:07 +02:00
score += 50 ;
score += 25 ;
2014-08-01 22:17:52 +02:00
}
2016-04-10 20:58:15 +01:00
if ( st -> codecpar -> codec_type == AVMEDIA_TYPE_AUDIO ) {
if ( st -> codecpar -> sample_rate )
2014-08-01 22:17:52 +02:00
score += 50 ;
}
2021-05-01 23:35:45 -03:00
if ( st -> internal -> codec_info_nb_frames )
2015-07-01 22:35:07 +02:00
score += 12 ;
2014-08-01 22:17:52 +02:00
2015-04-06 04:20:51 +02:00
if ( st -> discard != AVDISCARD_ALL )
score += 200 ;
2014-08-01 22:17:52 +02:00
if ( score > best_score ) {
best_score = score ;
best_stream = i ;
2004-01-13 22:02:49 +00:00
}
}
2014-08-01 22:17:52 +02:00
return best_stream ;
2004-01-13 22:02:49 +00:00
}
2014-01-16 01:53:03 +01:00
/** Flush the frame reader. */
2010-03-15 23:15:24 +00:00
void ff_read_frame_flush ( AVFormatContext * s )
2003-11-10 18:37:55 +00:00
{
AVStream * st ;
2009-12-12 15:26:33 +00:00
int i , j ;
2003-11-10 18:37:55 +00:00
flush_packet_queue ( s );
2014-01-16 01:53:03 +01:00
/* Reset read state for each stream. */
for ( i = 0 ; i < s -> nb_streams ; i ++ ) {
2003-11-10 18:37:55 +00:00
st = s -> streams [ i ];
2005-12-17 18:14:38 +00:00
2021-05-01 23:28:18 -03:00
if ( st -> internal -> parser ) {
av_parser_close ( st -> internal -> parser );
st -> internal -> parser = NULL ;
2003-11-10 18:37:55 +00:00
}
2021-05-01 23:05:21 -03:00
st -> internal -> last_IP_pts = AV_NOPTS_VALUE ;
2020-10-09 09:22:36 +02:00
st -> internal -> last_dts_for_order_check = AV_NOPTS_VALUE ;
2021-06-05 11:12:03 -03:00
if ( st -> internal -> first_dts == AV_NOPTS_VALUE )
st -> internal -> cur_dts = RELATIVE_TS_BASE ;
2014-01-26 23:35:38 +01:00
else
/* We set the current DTS to an unspecified origin. */
2021-06-05 11:12:03 -03:00
st -> internal -> cur_dts = AV_NOPTS_VALUE ;
2009-05-31 00:24:06 +00:00
2021-05-01 23:13:41 -03:00
st -> internal -> probe_packets = s -> max_probe_packets ;
2009-12-12 15:26:33 +00:00
2014-01-16 01:53:03 +01:00
for ( j = 0 ; j < MAX_REORDER_DELAY + 1 ; j ++ )
2020-10-09 09:22:36 +02:00
st -> internal -> pts_buffer [ j ] = AV_NOPTS_VALUE ;
2014-04-13 18:27:05 +02:00
2014-04-13 19:20:17 +02:00
if ( s -> internal -> inject_global_side_data )
2020-10-09 09:22:36 +02:00
st -> internal -> inject_global_side_data = 1 ;
2015-04-22 12:24:36 +02:00
2020-10-09 09:22:36 +02:00
st -> internal -> skip_samples = 0 ;
2003-11-10 18:37:55 +00:00
}
}
2021-06-05 11:09:03 -03:00
void avpriv_update_cur_dts ( AVFormatContext * s , AVStream * ref_st , int64_t timestamp )
2011-10-16 15:03:30 +02:00
{
2004-10-12 10:28:27 +00:00
int i ;
2014-01-16 01:53:03 +01:00
for ( i = 0 ; i < s -> nb_streams ; i ++ ) {
2004-10-22 13:15:18 +00:00
AVStream * st = s -> streams [ i ];
2004-10-12 10:28:27 +00:00
2021-06-05 11:12:03 -03:00
st -> internal -> cur_dts =
2014-01-16 01:53:03 +01:00
av_rescale ( timestamp ,
st -> time_base . den * ( int64_t ) ref_st -> time_base . num ,
st -> time_base . num * ( int64_t ) ref_st -> time_base . den );
2004-10-12 10:28:27 +00:00
}
}
2008-01-13 13:33:37 +00:00
void ff_reduce_index ( AVFormatContext * s , int stream_index )
{
2014-01-16 01:53:03 +01:00
AVStream * st = s -> streams [ stream_index ];
unsigned int max_entries = s -> max_index_size / sizeof ( AVIndexEntry );
2008-01-13 13:33:37 +00:00
2020-10-09 09:22:36 +02:00
if (( unsigned ) st -> internal -> nb_index_entries >= max_entries ) {
2008-01-13 13:33:37 +00:00
int i ;
2020-10-09 09:22:36 +02:00
for ( i = 0 ; 2 * i < st -> internal -> nb_index_entries ; i ++ )
st -> internal -> index_entries [ i ] = st -> internal -> index_entries [ 2 * i ];
st -> internal -> nb_index_entries = i ;
2008-01-13 13:33:37 +00:00
}
}
2011-01-22 20:03:22 +11:00
int ff_add_index_entry ( AVIndexEntry ** index_entries ,
int * nb_index_entries ,
unsigned int * index_entries_allocated_size ,
2014-01-16 01:53:03 +01:00
int64_t pos , int64_t timestamp ,
int size , int distance , int flags )
2003-11-10 18:37:55 +00:00
{
AVIndexEntry * entries , * ie ;
2004-01-13 22:02:49 +00:00
int index ;
2005-12-17 18:14:38 +00:00
2014-01-16 01:53:03 +01:00
if (( unsigned ) * nb_index_entries + 1 >= UINT_MAX / sizeof ( AVIndexEntry ))
2005-01-08 14:21:33 +00:00
return - 1 ;
2005-12-17 18:14:38 +00:00
2014-01-26 23:35:38 +01:00
if ( timestamp == AV_NOPTS_VALUE )
2012-07-24 18:10:48 +02:00
return AVERROR ( EINVAL );
2013-10-24 02:29:50 +02:00
if ( size < 0 || size > 0x3FFFFFFF )
return AVERROR ( EINVAL );
2012-03-07 22:13:39 +01:00
if ( is_relative ( timestamp )) //FIXME this maintains previous behavior but we should shift by the correct offset once known
timestamp -= RELATIVE_TS_BASE ;
2011-01-22 20:03:22 +11:00
entries = av_fast_realloc ( * index_entries ,
index_entries_allocated_size ,
( * nb_index_entries + 1 ) *
2003-11-10 18:37:55 +00:00
sizeof ( AVIndexEntry ));
2014-01-16 01:53:03 +01:00
if ( ! entries )
2005-01-08 14:21:33 +00:00
return - 1 ;
2014-01-16 01:53:03 +01:00
* index_entries = entries ;
2004-01-13 22:02:49 +00:00
2014-01-16 01:53:03 +01:00
index = ff_index_search_timestamp ( * index_entries , * nb_index_entries ,
timestamp , AVSEEK_FLAG_ANY );
2004-01-13 22:02:49 +00:00
2014-01-16 01:53:03 +01:00
if ( index < 0 ) {
index = ( * nb_index_entries ) ++ ;
ie = & entries [ index ];
2014-01-26 23:35:38 +01:00
av_assert0 ( index == 0 || ie [ - 1 ]. timestamp < timestamp );
2014-01-16 01:53:03 +01:00
} else {
ie = & entries [ index ];
if ( ie -> timestamp != timestamp ) {
if ( ie -> timestamp <= timestamp )
2004-10-13 23:58:28 +00:00
return - 1 ;
2014-01-16 01:53:03 +01:00
memmove ( entries + index + 1 , entries + index ,
sizeof ( AVIndexEntry ) * ( * nb_index_entries - index ));
2011-01-22 20:03:22 +11:00
( * nb_index_entries ) ++ ;
2014-01-16 01:53:03 +01:00
} else if ( ie -> pos == pos && distance < ie -> min_distance )
// do not reduce the distance
distance = ie -> min_distance ;
2004-01-17 18:06:52 +00:00
}
2004-10-10 22:05:43 +00:00
2014-01-16 01:53:03 +01:00
ie -> pos = pos ;
ie -> timestamp = timestamp ;
ie -> min_distance = distance ;
ie -> size = size ;
ie -> flags = flags ;
2005-12-17 18:14:38 +00:00
2004-01-17 18:06:52 +00:00
return index ;
2003-11-10 18:37:55 +00:00
}
2014-01-16 01:53:03 +01:00
int av_add_index_entry ( AVStream * st , int64_t pos , int64_t timestamp ,
int size , int distance , int flags )
2011-01-22 20:03:22 +11:00
{
2012-12-02 19:27:21 +01:00
timestamp = wrap_timestamp ( st , timestamp );
2020-10-09 09:22:36 +02:00
return ff_add_index_entry ( & st -> internal -> index_entries , & st -> internal -> nb_index_entries ,
& st -> internal -> index_entries_allocated_size , pos ,
2011-01-22 20:03:22 +11:00
timestamp , size , distance , flags );
}
int ff_index_search_timestamp ( const AVIndexEntry * entries , int nb_entries ,
int64_t wanted_timestamp , int flags )
2003-11-10 18:37:55 +00:00
{
int a , b , m ;
int64_t timestamp ;
2014-01-16 01:53:03 +01:00
a = - 1 ;
2004-10-10 22:05:43 +00:00
b = nb_entries ;
2004-01-13 22:02:49 +00:00
2014-01-16 01:53:03 +01:00
// Optimize appending index entries at the end.
if ( b && entries [ b - 1 ]. timestamp < wanted_timestamp )
a = b - 1 ;
2010-03-09 15:19:23 +00:00
2004-10-10 22:05:43 +00:00
while ( b - a > 1 ) {
2014-01-16 01:53:03 +01:00
m = ( a + b ) >> 1 ;
2016-09-15 13:36:18 -07:00
// Search for the next non-discarded packet.
2016-11-21 15:54:02 -08:00
while (( entries [ m ]. flags & AVINDEX_DISCARD_FRAME ) && m < b && m < nb_entries - 1 ) {
2016-09-15 13:36:18 -07:00
m ++ ;
if ( m == b && entries [ m ]. timestamp >= wanted_timestamp ) {
m = b - 1 ;
break ;
}
}
2003-11-10 18:37:55 +00:00
timestamp = entries [ m ]. timestamp ;
2014-01-16 01:53:03 +01:00
if ( timestamp >= wanted_timestamp )
2004-10-10 22:05:43 +00:00
b = m ;
2014-01-16 01:53:03 +01:00
if ( timestamp <= wanted_timestamp )
2004-01-13 22:02:49 +00:00
a = m ;
2003-11-10 18:37:55 +00:00
}
2014-01-16 01:53:03 +01:00
m = ( flags & AVSEEK_FLAG_BACKWARD ) ? a : b ;
2005-12-17 18:14:38 +00:00
2014-01-16 01:53:03 +01:00
if ( ! ( flags & AVSEEK_FLAG_ANY ))
while ( m >= 0 && m < nb_entries &&
! ( entries [ m ]. flags & AVINDEX_KEYFRAME ))
2005-03-13 00:13:01 +00:00
m += ( flags & AVSEEK_FLAG_BACKWARD ) ? - 1 : 1 ;
2004-10-10 22:05:43 +00:00
2014-01-16 01:53:03 +01:00
if ( m == nb_entries )
2004-10-10 22:05:43 +00:00
return - 1 ;
2014-01-16 01:53:03 +01:00
return m ;
2003-11-10 18:37:55 +00:00
}
2015-06-02 18:30:07 +02:00
void ff_configure_buffers_for_index ( AVFormatContext * s , int64_t time_tolerance )
{
int ist1 , ist2 ;
int64_t pos_delta = 0 ;
2015-07-15 03:35:08 +02:00
int64_t skip = 0 ;
2015-07-13 14:25:38 +02:00
//We could use URLProtocol flags here but as many user applications do not use URLProtocols this would be unreliable
2017-12-29 23:30:14 +01:00
const char * proto = avio_find_protocol_name ( s -> url );
2021-08-04 16:52:07 +02:00
FFIOContext * ctx ;
2015-07-13 14:25:38 +02:00
2020-01-28 16:49:14 -08:00
av_assert0 ( time_tolerance >= 0 );
2015-07-15 03:44:00 +02:00
if ( ! proto ) {
av_log ( s , AV_LOG_INFO ,
"Protocol name not provided, cannot determine if input is local or "
"a network protocol, buffers and access patterns cannot be configured "
"optimally without knowing the protocol \n " );
}
2015-07-14 21:08:24 +02:00
if ( proto && ! ( strcmp ( proto , "file" ) && strcmp ( proto , "pipe" ) && strcmp ( proto , "cache" )))
2015-07-13 14:25:38 +02:00
return ;
2015-06-02 18:30:07 +02:00
for ( ist1 = 0 ; ist1 < s -> nb_streams ; ist1 ++ ) {
AVStream * st1 = s -> streams [ ist1 ];
for ( ist2 = 0 ; ist2 < s -> nb_streams ; ist2 ++ ) {
AVStream * st2 = s -> streams [ ist2 ];
int i1 , i2 ;
if ( ist1 == ist2 )
continue ;
2020-10-09 09:22:36 +02:00
for ( i1 = i2 = 0 ; i1 < st1 -> internal -> nb_index_entries ; i1 ++ ) {
AVIndexEntry * e1 = & st1 -> internal -> index_entries [ i1 ];
2015-06-02 18:30:07 +02:00
int64_t e1_pts = av_rescale_q ( e1 -> timestamp , st1 -> time_base , AV_TIME_BASE_Q );
2015-07-15 03:35:08 +02:00
skip = FFMAX ( skip , e1 -> size );
2020-10-09 09:22:36 +02:00
for (; i2 < st2 -> internal -> nb_index_entries ; i2 ++ ) {
AVIndexEntry * e2 = & st2 -> internal -> index_entries [ i2 ];
2015-06-02 18:30:07 +02:00
int64_t e2_pts = av_rescale_q ( e2 -> timestamp , st2 -> time_base , AV_TIME_BASE_Q );
2020-01-28 16:49:14 -08:00
if ( e2_pts < e1_pts || e2_pts - ( uint64_t ) e1_pts < time_tolerance )
2015-06-02 18:30:07 +02:00
continue ;
pos_delta = FFMAX ( pos_delta , e1 -> pos - e2 -> pos );
break ;
}
}
}
}
pos_delta *= 2 ;
2021-08-04 16:52:07 +02:00
ctx = ffiocontext ( s -> pb );
2015-06-02 18:30:07 +02:00
/* XXX This could be adjusted depending on protocol*/
if ( s -> pb -> buffer_size < pos_delta && pos_delta < ( 1 << 24 )) {
av_log ( s , AV_LOG_VERBOSE , "Reconfiguring buffers to size %" PRId64 " \n " , pos_delta );
2019-08-07 22:48:28 +08:00
/* realloc the buffer and the original data will be retained */
if ( ffio_realloc_buf ( s -> pb , pos_delta )) {
av_log ( s , AV_LOG_ERROR , "Realloc buffer fail. \n " );
return ;
}
2021-08-04 16:52:07 +02:00
ctx -> short_seek_threshold = FFMAX ( ctx -> short_seek_threshold , pos_delta / 2 );
2015-06-02 18:30:07 +02:00
}
2015-07-15 03:35:08 +02:00
if ( skip < ( 1 << 23 )) {
2021-08-04 16:52:07 +02:00
ctx -> short_seek_threshold = FFMAX ( ctx -> short_seek_threshold , skip );
2015-07-15 03:35:08 +02:00
}
2015-06-02 18:30:07 +02:00
}
2014-01-16 01:53:03 +01:00
int av_index_search_timestamp ( AVStream * st , int64_t wanted_timestamp , int flags )
2011-01-22 20:03:22 +11:00
{
2020-10-09 09:22:36 +02:00
return ff_index_search_timestamp ( st -> internal -> index_entries , st -> internal -> nb_index_entries ,
2011-01-22 20:03:22 +11:00
wanted_timestamp , flags );
}
2021-03-23 15:36:22 -03:00
int avformat_index_get_entries_count ( const AVStream * st )
{
return st -> internal -> nb_index_entries ;
}
2021-04-08 14:16:53 -03:00
const AVIndexEntry * avformat_index_get_entry ( AVStream * st , int idx )
2021-03-23 15:36:22 -03:00
{
if ( idx < 0 || idx >= st -> internal -> nb_index_entries )
return NULL ;
return & st -> internal -> index_entries [ idx ];
}
2021-04-08 14:16:53 -03:00
const AVIndexEntry * avformat_index_get_entry_from_timestamp ( AVStream * st ,
2021-03-23 15:36:22 -03:00
int64_t wanted_timestamp ,
int flags )
{
int idx = ff_index_search_timestamp ( st -> internal -> index_entries ,
st -> internal -> nb_index_entries ,
wanted_timestamp , flags );
if ( idx < 0 )
return NULL ;
return & st -> internal -> index_entries [ idx ];
}
2012-12-02 19:27:21 +01:00
static int64_t ff_read_timestamp ( AVFormatContext * s , int stream_index , int64_t * ppos , int64_t pos_limit ,
int64_t ( * read_timestamp )( struct AVFormatContext * , int , int64_t * , int64_t ))
{
2013-02-18 19:48:44 +01:00
int64_t ts = read_timestamp ( s , stream_index , ppos , pos_limit );
if ( stream_index >= 0 )
ts = wrap_timestamp ( s -> streams [ stream_index ], ts );
return ts ;
2012-12-02 19:27:21 +01:00
}
2014-01-16 01:53:03 +01:00
int ff_seek_frame_binary ( AVFormatContext * s , int stream_index ,
int64_t target_ts , int flags )
2011-10-16 15:03:30 +02:00
{
2019-03-20 18:52:38 +01:00
const AVInputFormat * avif = s -> iformat ;
2009-03-05 19:15:14 +00:00
int64_t av_uninit ( pos_min ), av_uninit ( pos_max ), pos , pos_limit ;
2004-04-12 16:50:03 +00:00
int64_t ts_min , ts_max , ts ;
2006-11-14 01:34:36 +00:00
int index ;
2009-12-06 00:03:53 +00:00
int64_t ret ;
2004-04-12 16:50:03 +00:00
AVStream * st ;
2004-05-23 16:26:12 +00:00
if ( stream_index < 0 )
return - 1 ;
2005-12-17 18:14:38 +00:00
2015-04-20 03:19:29 +02:00
av_log ( s , AV_LOG_TRACE , "read_seek: %d %s \n " , stream_index , av_ts2str ( target_ts ));
2004-04-12 16:50:03 +00:00
2014-01-16 01:53:03 +01:00
ts_max =
ts_min = AV_NOPTS_VALUE ;
pos_limit = - 1 ; // GCC falsely says it may be uninitialized.
2004-04-12 16:50:03 +00:00
2014-01-16 01:53:03 +01:00
st = s -> streams [ stream_index ];
2020-10-09 09:22:36 +02:00
if ( st -> internal -> index_entries ) {
2004-04-12 16:50:03 +00:00
AVIndexEntry * e ;
2014-01-16 01:53:03 +01:00
/* FIXME: Whole function must be checked for non-keyframe entries in
* index case, especially read_timestamp(). */
index = av_index_search_timestamp ( st , target_ts ,
flags | AVSEEK_FLAG_BACKWARD );
index = FFMAX ( index , 0 );
2020-10-09 09:22:36 +02:00
e = & st -> internal -> index_entries [ index ];
2004-04-12 16:50:03 +00:00
2014-01-16 01:53:03 +01:00
if ( e -> timestamp <= target_ts || e -> pos == e -> min_distance ) {
pos_min = e -> pos ;
ts_min = e -> timestamp ;
2015-04-20 03:19:29 +02:00
av_log ( s , AV_LOG_TRACE , "using cached pos_min=0x%" PRIx64 " dts_min=%s \n " ,
2012-05-13 22:22:35 +02:00
pos_min , av_ts2str ( ts_min ));
2014-01-16 01:53:03 +01:00
} else {
2014-01-26 23:35:38 +01:00
av_assert1 ( index == 0 );
2004-04-12 16:50:03 +00:00
}
2005-12-17 18:14:38 +00:00
2014-01-16 01:53:03 +01:00
index = av_index_search_timestamp ( st , target_ts ,
flags & ~ AVSEEK_FLAG_BACKWARD );
2020-10-09 09:22:36 +02:00
av_assert0 ( index < st -> internal -> nb_index_entries );
2014-01-16 01:53:03 +01:00
if ( index >= 0 ) {
2020-10-09 09:22:36 +02:00
e = & st -> internal -> index_entries [ index ];
2013-04-19 17:30:13 +02:00
av_assert1 ( e -> timestamp >= target_ts );
2014-01-16 01:53:03 +01:00
pos_max = e -> pos ;
ts_max = e -> timestamp ;
pos_limit = pos_max - e -> min_distance ;
2015-03-16 08:57:35 +00:00
av_log ( s , AV_LOG_TRACE , "using cached pos_max=0x%" PRIx64 " pos_limit=0x%" PRIx64
2014-01-26 23:35:38 +01:00
" dts_max=%s \n " , pos_max , pos_limit , av_ts2str ( ts_max ));
2004-04-12 16:50:03 +00:00
}
}
2014-01-16 01:53:03 +01:00
pos = ff_gen_search ( s , stream_index , target_ts , pos_min , pos_max , pos_limit ,
ts_min , ts_max , flags , & ts , avif -> read_timestamp );
if ( pos < 0 )
2006-11-14 01:34:36 +00:00
return - 1 ;
/* do the seek */
2011-02-28 14:57:54 +01:00
if (( ret = avio_seek ( s -> pb , pos , SEEK_SET )) < 0 )
2009-12-06 00:03:53 +00:00
return ret ;
2006-11-14 01:34:36 +00:00
2011-10-21 22:26:13 +02:00
ff_read_frame_flush ( s );
2021-06-05 11:09:03 -03:00
avpriv_update_cur_dts ( s , st , ts );
2006-11-14 01:34:36 +00:00
return 0 ;
}
2013-07-06 21:52:07 +02:00
int ff_find_last_ts ( AVFormatContext * s , int stream_index , int64_t * ts , int64_t * pos ,
int64_t ( * read_timestamp )( struct AVFormatContext * , int , int64_t * , int64_t ))
{
2014-01-26 23:35:38 +01:00
int64_t step = 1024 ;
2013-07-06 21:52:07 +02:00
int64_t limit , ts_max ;
int64_t filesize = avio_size ( s -> pb );
2014-01-26 23:35:38 +01:00
int64_t pos_max = filesize - 1 ;
do {
2013-07-06 21:52:07 +02:00
limit = pos_max ;
pos_max = FFMAX ( 0 , ( pos_max ) - step );
2014-01-26 23:35:38 +01:00
ts_max = ff_read_timestamp ( s , stream_index ,
& pos_max , limit , read_timestamp );
step += step ;
} while ( ts_max == AV_NOPTS_VALUE && 2 * limit > step );
2013-07-06 21:52:07 +02:00
if ( ts_max == AV_NOPTS_VALUE )
return - 1 ;
2014-01-26 23:35:38 +01:00
for (;;) {
2013-07-06 21:52:07 +02:00
int64_t tmp_pos = pos_max + 1 ;
2014-01-26 23:35:38 +01:00
int64_t tmp_ts = ff_read_timestamp ( s , stream_index ,
& tmp_pos , INT64_MAX , read_timestamp );
if ( tmp_ts == AV_NOPTS_VALUE )
2013-07-06 21:52:07 +02:00
break ;
2013-09-04 00:58:16 +02:00
av_assert0 ( tmp_pos > pos_max );
2013-07-06 21:52:07 +02:00
ts_max = tmp_ts ;
pos_max = tmp_pos ;
2014-01-26 23:35:38 +01:00
if ( tmp_pos >= filesize )
2013-07-06 21:52:07 +02:00
break ;
}
if ( ts )
* ts = ts_max ;
if ( pos )
* pos = pos_max ;
return 0 ;
}
2011-10-16 15:03:30 +02:00
int64_t ff_gen_search ( AVFormatContext * s , int stream_index , int64_t target_ts ,
int64_t pos_min , int64_t pos_max , int64_t pos_limit ,
2014-01-16 01:53:03 +01:00
int64_t ts_min , int64_t ts_max ,
int flags , int64_t * ts_ret ,
int64_t ( * read_timestamp )( struct AVFormatContext * , int ,
int64_t * , int64_t ))
2011-10-16 15:03:30 +02:00
{
2006-11-14 01:34:36 +00:00
int64_t pos , ts ;
2013-07-06 21:52:07 +02:00
int64_t start_pos ;
2006-11-14 01:34:36 +00:00
int no_change ;
2013-07-06 21:52:07 +02:00
int ret ;
2006-11-14 01:34:36 +00:00
2015-04-20 03:19:29 +02:00
av_log ( s , AV_LOG_TRACE , "gen_seek: %d %s \n " , stream_index , av_ts2str ( target_ts ));
2006-11-14 01:34:36 +00:00
2014-01-16 01:53:03 +01:00
if ( ts_min == AV_NOPTS_VALUE ) {
2015-02-06 14:53:40 +01:00
pos_min = s -> internal -> data_offset ;
2014-01-26 23:35:38 +01:00
ts_min = ff_read_timestamp ( s , stream_index , & pos_min , INT64_MAX , read_timestamp );
2004-04-12 16:50:03 +00:00
if ( ts_min == AV_NOPTS_VALUE )
return - 1 ;
}
2014-01-26 23:35:38 +01:00
if ( ts_min >= target_ts ) {
* ts_ret = ts_min ;
2011-10-21 20:45:00 +02:00
return pos_min ;
}
2014-01-26 23:35:38 +01:00
if ( ts_max == AV_NOPTS_VALUE ) {
2013-07-06 21:52:07 +02:00
if (( ret = ff_find_last_ts ( s , stream_index , & ts_max , & pos_max , read_timestamp )) < 0 )
return ret ;
2014-01-16 01:53:03 +01:00
pos_limit = pos_max ;
2004-04-12 16:50:03 +00:00
}
2014-01-26 23:35:38 +01:00
if ( ts_max <= target_ts ) {
* ts_ret = ts_max ;
2011-10-21 20:45:00 +02:00
return pos_max ;
}
2014-12-09 17:53:30 +01:00
av_assert0 ( ts_min < ts_max );
2006-02-02 19:23:33 +00:00
2014-01-16 01:53:03 +01:00
no_change = 0 ;
2004-04-12 16:50:03 +00:00
while ( pos_min < pos_limit ) {
2015-04-20 03:19:29 +02:00
av_log ( s , AV_LOG_TRACE ,
2014-01-26 23:35:38 +01:00
"pos_min=0x%" PRIx64 " pos_max=0x%" PRIx64 " dts_min=%s dts_max=%s \n " ,
2012-05-13 22:22:35 +02:00
pos_min , pos_max , av_ts2str ( ts_min ), av_ts2str ( ts_max ));
2014-12-09 17:57:35 +01:00
av_assert0 ( pos_limit <= pos_max );
2004-04-12 16:50:03 +00:00
2014-01-16 01:53:03 +01:00
if ( no_change == 0 ) {
int64_t approximate_keyframe_distance = pos_max - pos_limit ;
2004-04-12 16:50:03 +00:00
// interpolate position (better than dichotomy)
2014-01-16 01:53:03 +01:00
pos = av_rescale ( target_ts - ts_min , pos_max - pos_min ,
ts_max - ts_min ) +
pos_min - approximate_keyframe_distance ;
} else if ( no_change == 1 ) {
// bisection if interpolation did not change min / max pos last time
pos = ( pos_min + pos_limit ) >> 1 ;
} else {
2008-01-16 22:14:26 +00:00
/* linear search if bisection failed, can only happen if there
2014-01-16 01:53:03 +01:00
* are very few or no keyframes between min/max */
pos = pos_min ;
2004-04-12 16:50:03 +00:00
}
2014-01-16 01:53:03 +01:00
if ( pos <= pos_min )
pos = pos_min + 1 ;
else if ( pos > pos_limit )
pos = pos_limit ;
start_pos = pos ;
2004-04-12 16:50:03 +00:00
2014-01-16 01:53:03 +01:00
// May pass pos_limit instead of -1.
2014-01-26 23:35:38 +01:00
ts = ff_read_timestamp ( s , stream_index , & pos , INT64_MAX , read_timestamp );
2014-01-16 01:53:03 +01:00
if ( pos == pos_max )
2004-04-12 16:50:03 +00:00
no_change ++ ;
else
2014-01-16 01:53:03 +01:00
no_change = 0 ;
2015-04-20 03:19:29 +02:00
av_log ( s , AV_LOG_TRACE , "%" PRId64 " %" PRId64 " %" PRId64 " / %s %s %s"
2014-01-26 23:35:38 +01:00
" target:%s limit:%" PRId64 " start:%" PRId64 " noc:%d \n " ,
2012-05-13 22:22:35 +02:00
pos_min , pos , pos_max ,
av_ts2str ( ts_min ), av_ts2str ( ts ), av_ts2str ( ts_max ), av_ts2str ( target_ts ),
2011-06-07 13:18:12 +02:00
pos_limit , start_pos , no_change );
2014-01-16 01:53:03 +01:00
if ( ts == AV_NOPTS_VALUE ) {
2007-04-22 18:48:07 +00:00
av_log ( s , AV_LOG_ERROR , "read_timestamp() failed in the middle \n " );
return - 1 ;
}
2004-10-10 22:05:43 +00:00
if ( target_ts <= ts ) {
2004-04-12 16:50:03 +00:00
pos_limit = start_pos - 1 ;
2014-01-16 01:53:03 +01:00
pos_max = pos ;
ts_max = ts ;
2004-10-10 22:05:43 +00:00
}
if ( target_ts >= ts ) {
2004-04-12 16:50:03 +00:00
pos_min = pos ;
2014-01-16 01:53:03 +01:00
ts_min = ts ;
2004-04-12 16:50:03 +00:00
}
}
2005-12-17 18:14:38 +00:00
2014-01-16 01:53:03 +01:00
pos = ( flags & AVSEEK_FLAG_BACKWARD ) ? pos_min : pos_max ;
ts = ( flags & AVSEEK_FLAG_BACKWARD ) ? ts_min : ts_max ;
2011-10-21 22:08:39 +02:00
#if 0
2004-04-12 16:50:03 +00:00
pos_min = pos;
2014-01-26 23:35:38 +01:00
ts_min = ff_read_timestamp(s, stream_index, &pos_min, INT64_MAX, read_timestamp);
2004-04-12 16:50:03 +00:00
pos_min++;
2012-12-02 19:27:21 +01:00
ts_max = ff_read_timestamp(s, stream_index, &pos_min, INT64_MAX, read_timestamp);
2015-04-20 03:19:29 +02:00
av_log(s, AV_LOG_TRACE, "pos=0x%"PRIx64" %s<=%s<=%s\n",
2012-05-13 22:22:35 +02:00
pos, av_ts2str(ts_min), av_ts2str(target_ts), av_ts2str(ts_max));
2011-10-21 22:08:39 +02:00
#endif
2014-01-16 01:53:03 +01:00
* ts_ret = ts ;
2006-11-14 01:34:36 +00:00
return pos ;
2004-04-12 16:50:03 +00:00
}
2014-01-16 01:53:03 +01:00
static int seek_frame_byte ( AVFormatContext * s , int stream_index ,
int64_t pos , int flags )
{
2004-10-10 22:05:43 +00:00
int64_t pos_min , pos_max ;
2015-02-06 14:53:40 +01:00
pos_min = s -> internal -> data_offset ;
2011-03-04 19:57:36 +01:00
pos_max = avio_size ( s -> pb ) - 1 ;
2004-10-10 22:05:43 +00:00
2014-01-16 01:53:03 +01:00
if ( pos < pos_min )
pos = pos_min ;
else if ( pos > pos_max )
pos = pos_max ;
2004-10-10 22:05:43 +00:00
2011-02-28 14:57:54 +01:00
avio_seek ( s -> pb , pos , SEEK_SET );
2004-10-10 22:05:43 +00:00
2013-04-04 04:01:12 +02:00
s -> io_repositioned = 1 ;
2004-10-10 22:05:43 +00:00
return 0 ;
}
2014-01-16 01:53:03 +01:00
static int seek_frame_generic ( AVFormatContext * s , int stream_index ,
int64_t timestamp , int flags )
2003-11-10 18:37:55 +00:00
{
2009-12-01 22:56:44 +00:00
int index ;
int64_t ret ;
2003-11-10 18:37:55 +00:00
AVStream * st ;
AVIndexEntry * ie ;
st = s -> streams [ stream_index ];
2007-02-05 23:04:48 +00:00
2005-03-13 00:13:01 +00:00
index = av_index_search_timestamp ( st , timestamp , flags );
2007-02-05 23:04:48 +00:00
2020-10-09 09:22:36 +02:00
if ( index < 0 && st -> internal -> nb_index_entries &&
timestamp < st -> internal -> index_entries [ 0 ]. timestamp )
2010-02-03 23:59:48 +00:00
return - 1 ;
2020-10-09 09:22:36 +02:00
if ( index < 0 || index == st -> internal -> nb_index_entries - 1 ) {
2021-01-31 13:05:49 -03:00
AVPacket * pkt = s -> internal -> pkt ;
2014-01-26 23:35:38 +01:00
int nonkey = 0 ;
2007-02-05 23:04:48 +00:00
2020-10-09 09:22:36 +02:00
if ( st -> internal -> nb_index_entries ) {
av_assert0 ( st -> internal -> index_entries );
ie = & st -> internal -> index_entries [ st -> internal -> nb_index_entries - 1 ];
2011-02-28 14:57:54 +01:00
if (( ret = avio_seek ( s -> pb , ie -> pos , SEEK_SET )) < 0 )
2008-07-31 18:02:55 +00:00
return ret ;
2021-08-22 08:27:01 +02:00
s -> io_repositioned = 1 ;
2021-06-05 11:09:03 -03:00
avpriv_update_cur_dts ( s , st , ie -> timestamp );
2014-01-16 01:53:03 +01:00
} else {
2015-02-06 14:53:40 +01:00
if (( ret = avio_seek ( s -> pb , s -> internal -> data_offset , SEEK_SET )) < 0 )
2008-07-31 18:02:55 +00:00
return ret ;
2021-08-22 08:27:01 +02:00
s -> io_repositioned = 1 ;
2008-07-31 18:02:55 +00:00
}
2021-01-31 13:05:49 -03:00
av_packet_unref ( pkt );
2011-09-13 15:27:01 -07:00
for (;;) {
2011-09-13 15:26:25 -07:00
int read_status ;
2014-01-16 01:53:03 +01:00
do {
2021-01-31 13:05:49 -03:00
read_status = av_read_frame ( s , pkt );
2011-09-13 15:26:25 -07:00
} while ( read_status == AVERROR ( EAGAIN ));
if ( read_status < 0 )
2007-02-05 23:04:48 +00:00
break ;
2021-01-31 13:05:49 -03:00
if ( stream_index == pkt -> stream_index && pkt -> dts > timestamp ) {
if ( pkt -> flags & AV_PKT_FLAG_KEY ) {
av_packet_unref ( pkt );
2007-02-05 23:04:48 +00:00
break ;
2016-01-01 20:23:37 +01:00
}
2016-04-10 20:58:15 +01:00
if ( nonkey ++ > 1000 && st -> codecpar -> codec_id != AV_CODEC_ID_CDGRAPHICS ) {
2011-10-05 18:23:47 +02:00
av_log ( s , AV_LOG_ERROR , "seek_frame_generic failed as this stream seems to contain no keyframes after the target timestamp, %d non keyframes found \n " , nonkey );
2021-01-31 13:05:49 -03:00
av_packet_unref ( pkt );
2011-10-05 18:23:47 +02:00
break ;
}
2007-02-05 23:04:48 +00:00
}
2021-01-31 13:05:49 -03:00
av_packet_unref ( pkt );
2007-02-05 23:04:48 +00:00
}
index = av_index_search_timestamp ( st , timestamp , flags );
}
2003-11-10 18:37:55 +00:00
if ( index < 0 )
return - 1 ;
2010-03-15 23:15:24 +00:00
ff_read_frame_flush ( s );
2014-01-16 01:53:03 +01:00
if ( s -> iformat -> read_seek )
if ( s -> iformat -> read_seek ( s , stream_index , timestamp , flags ) >= 0 )
2007-02-05 23:04:48 +00:00
return 0 ;
2020-10-09 09:22:36 +02:00
ie = & st -> internal -> index_entries [ index ];
2011-02-28 14:57:54 +01:00
if (( ret = avio_seek ( s -> pb , ie -> pos , SEEK_SET )) < 0 )
2008-07-31 18:02:55 +00:00
return ret ;
2021-08-22 08:27:01 +02:00
s -> io_repositioned = 1 ;
2021-06-05 11:09:03 -03:00
avpriv_update_cur_dts ( s , st , ie -> timestamp );
2004-05-23 16:26:12 +00:00
2003-11-10 18:37:55 +00:00
return 0 ;
}
2012-03-18 17:34:14 +01:00
static int seek_frame_internal ( AVFormatContext * s , int stream_index ,
int64_t timestamp , int flags )
2003-11-10 18:37:55 +00:00
{
int ret ;
2004-05-23 16:26:12 +00:00
AVStream * st ;
2005-12-17 18:14:38 +00:00
2011-09-16 19:02:23 -04:00
if ( flags & AVSEEK_FLAG_BYTE ) {
2011-10-02 11:57:53 -04:00
if ( s -> iformat -> flags & AVFMT_NO_BYTE_SEEK )
return - 1 ;
2011-09-16 19:02:23 -04:00
ff_read_frame_flush ( s );
2011-07-15 20:27:43 +02:00
return seek_frame_byte ( s , stream_index , timestamp , flags );
2011-09-16 19:02:23 -04:00
}
2005-12-17 18:14:38 +00:00
2014-01-16 01:53:03 +01:00
if ( stream_index < 0 ) {
stream_index = av_find_default_stream_index ( s );
if ( stream_index < 0 )
2004-05-23 16:26:12 +00:00
return - 1 ;
2005-12-17 18:14:38 +00:00
2014-01-16 01:53:03 +01:00
st = s -> streams [ stream_index ];
2011-08-22 18:47:24 -07:00
/* timestamp for default must be expressed in AV_TIME_BASE units */
2014-01-16 01:53:03 +01:00
timestamp = av_rescale ( timestamp , st -> time_base . den ,
AV_TIME_BASE * ( int64_t ) st -> time_base . num );
2004-05-23 16:26:12 +00:00
}
2003-11-10 18:37:55 +00:00
/* first, we try the format specific seek */
2011-09-16 19:02:23 -04:00
if ( s -> iformat -> read_seek ) {
ff_read_frame_flush ( s );
2004-10-10 22:05:43 +00:00
ret = s -> iformat -> read_seek ( s , stream_index , timestamp , flags );
2011-09-16 19:02:23 -04:00
} else
2003-11-10 18:37:55 +00:00
ret = - 1 ;
2014-01-16 01:53:03 +01:00
if ( ret >= 0 )
2003-11-10 18:37:55 +00:00
return 0 ;
2004-04-12 16:50:03 +00:00
2014-01-16 01:53:03 +01:00
if ( s -> iformat -> read_timestamp &&
! ( s -> iformat -> flags & AVFMT_NOBINSEARCH )) {
2011-09-16 19:02:23 -04:00
ff_read_frame_flush ( s );
2011-10-16 15:03:30 +02:00
return ff_seek_frame_binary ( s , stream_index , timestamp , flags );
2011-09-16 19:02:23 -04:00
} else if ( ! ( s -> iformat -> flags & AVFMT_NOGENSEARCH )) {
ff_read_frame_flush ( s );
2011-07-15 20:27:43 +02:00
return seek_frame_generic ( s , stream_index , timestamp , flags );
2014-01-16 01:53:03 +01:00
} else
2011-05-17 17:30:05 +02:00
return - 1 ;
2003-11-10 18:37:55 +00:00
}
2014-01-16 01:53:03 +01:00
int av_seek_frame ( AVFormatContext * s , int stream_index ,
int64_t timestamp , int flags )
2012-03-18 17:34:14 +01:00
{
2013-04-29 23:58:22 +02:00
int ret ;
if ( s -> iformat -> read_seek2 && ! s -> iformat -> read_seek ) {
int64_t min_ts = INT64_MIN , max_ts = INT64_MAX ;
if (( flags & AVSEEK_FLAG_BACKWARD ))
max_ts = timestamp ;
else
min_ts = timestamp ;
return avformat_seek_file ( s , stream_index , min_ts , timestamp , max_ts ,
flags & ~ AVSEEK_FLAG_BACKWARD );
}
2013-05-04 16:58:41 +02:00
2013-04-29 23:58:22 +02:00
ret = seek_frame_internal ( s , stream_index , timestamp , flags );
2012-03-18 17:34:14 +01:00
if ( ret >= 0 )
2013-03-08 17:28:42 +01:00
ret = avformat_queue_attached_pictures ( s );
2012-03-18 17:34:14 +01:00
return ret ;
}
2014-01-16 01:53:03 +01:00
int avformat_seek_file ( AVFormatContext * s , int stream_index , int64_t min_ts ,
int64_t ts , int64_t max_ts , int flags )
2009-03-14 15:51:46 +00:00
{
2014-01-16 01:53:03 +01:00
if ( min_ts > ts || max_ts < ts )
2009-03-14 15:51:46 +00:00
return - 1 ;
2013-03-20 12:27:42 +01:00
if ( stream_index < - 1 || stream_index >= ( int ) s -> nb_streams )
return AVERROR ( EINVAL );
2009-03-14 15:51:46 +00:00
2014-01-26 23:35:38 +01:00
if ( s -> seek2any > 0 )
2012-08-06 01:25:57 +02:00
flags |= AVSEEK_FLAG_ANY ;
2013-05-03 10:31:33 +02:00
flags &= ~ AVSEEK_FLAG_BACKWARD ;
2012-08-06 01:25:57 +02:00
2011-09-16 19:02:23 -04:00
if ( s -> iformat -> read_seek2 ) {
2012-03-18 17:34:14 +01:00
int ret ;
2011-09-16 19:02:23 -04:00
ff_read_frame_flush ( s );
2013-01-02 22:55:42 +01:00
if ( stream_index == - 1 && s -> nb_streams == 1 ) {
AVRational time_base = s -> streams [ 0 ] -> time_base ;
ts = av_rescale_q ( ts , AV_TIME_BASE_Q , time_base );
min_ts = av_rescale_rnd ( min_ts , time_base . den ,
time_base . num * ( int64_t ) AV_TIME_BASE ,
2013-01-02 22:01:41 +01:00
AV_ROUND_UP | AV_ROUND_PASS_MINMAX );
2013-01-02 22:55:42 +01:00
max_ts = av_rescale_rnd ( max_ts , time_base . den ,
time_base . num * ( int64_t ) AV_TIME_BASE ,
2013-01-02 22:01:41 +01:00
AV_ROUND_DOWN | AV_ROUND_PASS_MINMAX );
2016-09-14 16:13:45 +08:00
stream_index = 0 ;
2013-01-02 22:55:42 +01:00
}
2014-01-16 01:53:03 +01:00
ret = s -> iformat -> read_seek2 ( s , stream_index , min_ts ,
ts , max_ts , flags );
2012-03-18 17:34:14 +01:00
if ( ret >= 0 )
2013-03-08 17:28:42 +01:00
ret = avformat_queue_attached_pictures ( s );
2012-03-18 17:34:14 +01:00
return ret ;
2011-09-16 19:02:23 -04:00
}
2009-03-14 15:51:46 +00:00
2014-01-16 01:53:03 +01:00
if ( s -> iformat -> read_timestamp ) {
// try to seek via read_timestamp()
2009-03-14 15:51:46 +00:00
}
2012-08-21 01:02:13 +02:00
// Fall back on old API if new is not implemented but old is.
// Note the old API has somewhat different semantics.
2012-02-18 00:16:58 +01:00
if ( s -> iformat -> read_seek || 1 ) {
2012-09-11 02:51:09 +02:00
int dir = ( ts - ( uint64_t ) min_ts > ( uint64_t ) max_ts - ts ? AVSEEK_FLAG_BACKWARD : 0 );
2012-02-18 00:16:58 +01:00
int ret = av_seek_frame ( s , stream_index , ts , flags | dir );
if ( ret < 0 && ts != min_ts && max_ts != ts ) {
ret = av_seek_frame ( s , stream_index , dir ? max_ts : min_ts , flags | dir );
if ( ret >= 0 )
ret = av_seek_frame ( s , stream_index , ts , flags | ( dir ^ AVSEEK_FLAG_BACKWARD ));
}
return ret ;
}
2009-03-14 15:51:46 +00:00
2011-07-15 20:27:43 +02:00
// try some generic seek like seek_frame_generic() but with new ts semantics
2013-01-03 16:02:47 +01:00
return - 1 ; //unreachable
2009-03-14 15:51:46 +00:00
}
2014-09-30 18:46:49 +02:00
int avformat_flush ( AVFormatContext * s )
{
ff_read_frame_flush ( s );
return 0 ;
}
2003-10-29 14:20:56 +00:00
/*******************************************************/
2003-08-08 18:02:23 +00:00
2005-06-28 12:55:08 +00:00
/**
2010-06-30 15:38:06 +00:00
* Return TRUE if the stream has accurate duration in any stream.
2005-06-28 12:55:08 +00:00
*
2007-09-05 16:47:48 +00:00
* @return TRUE if the stream has accurate duration for at least one component.
2005-06-28 12:55:08 +00:00
*/
2011-07-15 20:27:43 +02:00
static int has_duration ( AVFormatContext * ic )
2003-08-08 18:02:23 +00:00
{
int i ;
AVStream * st ;
2014-01-16 01:53:03 +01:00
for ( i = 0 ; i < ic -> nb_streams ; i ++ ) {
2003-08-08 18:02:23 +00:00
st = ic -> streams [ i ];
2007-09-05 16:47:48 +00:00
if ( st -> duration != AV_NOPTS_VALUE )
2003-08-08 18:02:23 +00:00
return 1 ;
}
2012-04-24 22:13:02 -07:00
if ( ic -> duration != AV_NOPTS_VALUE )
2012-04-12 22:00:57 -07:00
return 1 ;
2003-08-08 18:02:23 +00:00
return 0 ;
}
2005-06-28 12:55:08 +00:00
/**
* Estimate the stream timings from the one of each components.
*
* Also computes the global bitrate if possible.
*/
2011-07-15 20:27:43 +02:00
static void update_stream_timings ( AVFormatContext * ic )
2003-08-08 18:02:23 +00:00
{
2016-10-05 06:37:57 -05:00
int64_t start_time , start_time1 , start_time_text , end_time , end_time1 , end_time_text ;
2018-04-19 13:29:24 -07:00
int64_t duration , duration1 , duration_text , filesize ;
2003-08-08 18:02:23 +00:00
int i ;
2012-10-23 18:11:26 +02:00
AVProgram * p ;
2003-08-08 18:02:23 +00:00
2006-12-07 00:47:37 +00:00
start_time = INT64_MAX ;
2011-05-12 03:40:21 +02:00
start_time_text = INT64_MAX ;
2014-01-16 01:53:03 +01:00
end_time = INT64_MIN ;
2016-10-05 06:37:57 -05:00
end_time_text = INT64_MIN ;
2014-01-16 01:53:03 +01:00
duration = INT64_MIN ;
2018-04-19 13:29:24 -07:00
duration_text = INT64_MIN ;
2014-01-16 01:53:03 +01:00
for ( i = 0 ; i < ic -> nb_streams ; i ++ ) {
2018-04-19 16:50:43 -07:00
AVStream * st = ic -> streams [ i ];
int is_text = st -> codecpar -> codec_type == AVMEDIA_TYPE_SUBTITLE ||
st -> codecpar -> codec_type == AVMEDIA_TYPE_DATA ;
2008-01-21 23:43:25 +00:00
if ( st -> start_time != AV_NOPTS_VALUE && st -> time_base . den ) {
2014-01-16 01:53:03 +01:00
start_time1 = av_rescale_q ( st -> start_time , st -> time_base ,
AV_TIME_BASE_Q );
2018-04-19 16:50:43 -07:00
if ( is_text )
start_time_text = FFMIN ( start_time_text , start_time1 );
else
2012-06-14 10:54:09 -06:00
start_time = FFMIN ( start_time , start_time1 );
2015-12-02 22:59:56 +01:00
end_time1 = av_rescale_q_rnd ( st -> duration , st -> time_base ,
AV_TIME_BASE_Q ,
AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX );
2016-09-24 13:07:39 +02:00
if ( end_time1 != AV_NOPTS_VALUE && ( end_time1 > 0 ? start_time1 <= INT64_MAX - end_time1 : start_time1 >= INT64_MIN - end_time1 )) {
2015-12-02 22:59:56 +01:00
end_time1 += start_time1 ;
2018-04-19 16:50:43 -07:00
if ( is_text )
2016-10-05 06:37:57 -05:00
end_time_text = FFMAX ( end_time_text , end_time1 );
else
end_time = FFMAX ( end_time , end_time1 );
2003-08-08 18:02:23 +00:00
}
2014-01-26 23:35:38 +01:00
for ( p = NULL ; ( p = av_find_program_from_stream ( ic , p , i )); ) {
if ( p -> start_time == AV_NOPTS_VALUE || p -> start_time > start_time1 )
2012-10-23 18:11:26 +02:00
p -> start_time = start_time1 ;
2014-01-26 23:35:38 +01:00
if ( p -> end_time < end_time1 )
2012-10-23 18:11:26 +02:00
p -> end_time = end_time1 ;
}
2003-08-08 18:02:23 +00:00
}
2007-09-05 16:47:48 +00:00
if ( st -> duration != AV_NOPTS_VALUE ) {
2014-01-16 01:53:03 +01:00
duration1 = av_rescale_q ( st -> duration , st -> time_base ,
AV_TIME_BASE_Q );
2018-04-19 16:50:43 -07:00
if ( is_text )
2018-04-19 13:29:24 -07:00
duration_text = FFMAX ( duration_text , duration1 );
else
duration = FFMAX ( duration , duration1 );
2007-09-05 16:47:48 +00:00
}
2003-08-08 18:02:23 +00:00
}
2018-08-20 12:59:32 -07:00
if ( start_time == INT64_MAX || ( start_time > start_time_text && start_time - ( uint64_t ) start_time_text < AV_TIME_BASE ))
2011-05-12 03:40:21 +02:00
start_time = start_time_text ;
2014-01-26 23:35:38 +01:00
else if ( start_time > start_time_text )
2012-06-12 19:28:08 +02:00
av_log ( ic , AV_LOG_VERBOSE , "Ignoring outlier non primary stream starttime %f \n " , start_time_text / ( float ) AV_TIME_BASE );
2018-04-19 16:50:43 -07:00
if ( end_time == INT64_MIN || ( end_time < end_time_text && end_time_text - ( uint64_t ) end_time < AV_TIME_BASE ))
2016-10-05 06:37:57 -05:00
end_time = end_time_text ;
2018-04-19 16:50:43 -07:00
else if ( end_time < end_time_text )
2016-10-05 06:37:57 -05:00
av_log ( ic , AV_LOG_VERBOSE , "Ignoring outlier non primary stream endtime %f \n " , end_time_text / ( float ) AV_TIME_BASE );
2018-04-19 13:29:24 -07:00
if ( duration == INT64_MIN || ( duration < duration_text && duration_text - duration < AV_TIME_BASE ))
duration = duration_text ;
else if ( duration < duration_text )
av_log ( ic , AV_LOG_VERBOSE , "Ignoring outlier non primary stream duration %f \n " , duration_text / ( float ) AV_TIME_BASE );
2006-12-07 00:47:37 +00:00
if ( start_time != INT64_MAX ) {
2003-08-08 18:02:23 +00:00
ic -> start_time = start_time ;
2012-10-23 18:11:26 +02:00
if ( end_time != INT64_MIN ) {
2016-10-05 06:38:24 -05:00
if ( ic -> nb_programs > 1 ) {
2014-01-26 23:35:38 +01:00
for ( i = 0 ; i < ic -> nb_programs ; i ++ ) {
2012-10-23 18:11:26 +02:00
p = ic -> programs [ i ];
2016-12-03 03:02:41 +01:00
if ( p -> start_time != AV_NOPTS_VALUE &&
p -> end_time > p -> start_time &&
p -> end_time - ( uint64_t ) p -> start_time <= INT64_MAX )
2012-10-23 18:11:26 +02:00
duration = FFMAX ( duration , p -> end_time - p -> start_time );
}
2016-12-03 03:02:41 +01:00
} else if ( end_time >= start_time && end_time - ( uint64_t ) start_time <= INT64_MAX ) {
2012-10-23 18:11:26 +02:00
duration = FFMAX ( duration , end_time - start_time );
2016-12-03 03:02:41 +01:00
}
2012-10-23 18:11:26 +02:00
}
2007-09-05 16:47:48 +00:00
}
2012-09-10 16:57:31 +02:00
if ( duration != INT64_MIN && duration > 0 && ic -> duration == AV_NOPTS_VALUE ) {
2007-09-05 16:47:48 +00:00
ic -> duration = duration ;
2011-09-13 01:02:48 +02:00
}
2016-05-16 13:43:02 +02:00
if ( ic -> pb && ( filesize = avio_size ( ic -> pb )) > 0 && ic -> duration > 0 ) {
2014-01-26 23:35:38 +01:00
/* compute the bitrate */
double bitrate = ( double ) filesize * 8.0 * AV_TIME_BASE /
( double ) ic -> duration ;
2015-09-16 01:46:50 -03:00
if ( bitrate >= 0 && bitrate <= INT64_MAX )
2014-01-26 23:35:38 +01:00
ic -> bit_rate = bitrate ;
2003-08-08 18:02:23 +00:00
}
}
static void fill_all_stream_timings ( AVFormatContext * ic )
{
int i ;
AVStream * st ;
2011-07-15 20:27:43 +02:00
update_stream_timings ( ic );
2014-01-16 01:53:03 +01:00
for ( i = 0 ; i < ic -> nb_streams ; i ++ ) {
2003-08-08 18:02:23 +00:00
st = ic -> streams [ i ];
if ( st -> start_time == AV_NOPTS_VALUE ) {
2014-01-16 01:53:03 +01:00
if ( ic -> start_time != AV_NOPTS_VALUE )
st -> start_time = av_rescale_q ( ic -> start_time , AV_TIME_BASE_Q ,
st -> time_base );
if ( ic -> duration != AV_NOPTS_VALUE )
st -> duration = av_rescale_q ( ic -> duration , AV_TIME_BASE_Q ,
st -> time_base );
2003-08-08 18:02:23 +00:00
}
}
}
2011-07-15 20:27:43 +02:00
static void estimate_timings_from_bit_rate ( AVFormatContext * ic )
2003-08-08 18:02:23 +00:00
{
int64_t filesize , duration ;
2013-09-03 14:16:42 +02:00
int i , show_warning = 0 ;
2003-08-08 18:02:23 +00:00
AVStream * st ;
/* if bit_rate is already set, we believe it */
2010-12-20 09:58:27 +00:00
if ( ic -> bit_rate <= 0 ) {
2016-06-22 13:58:42 +02:00
int64_t bit_rate = 0 ;
2014-01-16 01:53:03 +01:00
for ( i = 0 ; i < ic -> nb_streams ; i ++ ) {
2003-08-08 18:02:23 +00:00
st = ic -> streams [ i ];
2016-06-22 13:59:19 +02:00
if ( st -> codecpar -> bit_rate <= 0 && st -> internal -> avctx -> bit_rate > 0 )
st -> codecpar -> bit_rate = st -> internal -> avctx -> bit_rate ;
2014-06-18 20:42:52 +02:00
if ( st -> codecpar -> bit_rate > 0 ) {
2016-06-22 13:58:42 +02:00
if ( INT64_MAX - st -> codecpar -> bit_rate < bit_rate ) {
2013-08-24 21:30:46 +02:00
bit_rate = 0 ;
break ;
}
2014-06-18 20:42:52 +02:00
bit_rate += st -> codecpar -> bit_rate ;
2021-05-01 23:35:45 -03:00
} else if ( st -> codecpar -> codec_type == AVMEDIA_TYPE_VIDEO && st -> internal -> codec_info_nb_frames > 1 ) {
2014-12-13 19:20:10 +01:00
// If we have a videostream with packets but without a bitrate
2014-12-13 20:52:31 +01:00
// then consider the sum not known
2014-12-13 19:20:10 +01:00
bit_rate = 0 ;
break ;
2013-08-24 21:30:46 +02:00
}
2003-08-08 18:02:23 +00:00
}
ic -> bit_rate = bit_rate ;
}
/* if duration is already set, we believe it */
2005-12-17 18:14:38 +00:00
if ( ic -> duration == AV_NOPTS_VALUE &&
2011-10-09 14:12:14 +02:00
ic -> bit_rate != 0 ) {
filesize = ic -> pb ? avio_size ( ic -> pb ) : 0 ;
2015-02-11 02:13:46 +01:00
if ( filesize > ic -> internal -> data_offset ) {
filesize -= ic -> internal -> data_offset ;
2014-01-16 01:53:03 +01:00
for ( i = 0 ; i < ic -> nb_streams ; i ++ ) {
2014-01-26 23:35:38 +01:00
st = ic -> streams [ i ];
2013-03-28 01:43:55 +01:00
if ( st -> time_base . num <= INT64_MAX / ic -> bit_rate
&& st -> duration == AV_NOPTS_VALUE ) {
2020-06-21 12:24:04 +02:00
duration = av_rescale ( filesize , 8LL * st -> time_base . den ,
2014-01-26 23:35:38 +01:00
ic -> bit_rate *
( int64_t ) st -> time_base . num );
2003-08-08 18:02:23 +00:00
st -> duration = duration ;
2013-03-30 08:24:51 +01:00
show_warning = 1 ;
2013-03-28 01:43:55 +01:00
}
2003-08-08 18:02:23 +00:00
}
}
}
2013-03-30 08:24:51 +01:00
if ( show_warning )
2014-01-26 23:35:38 +01:00
av_log ( ic , AV_LOG_WARNING ,
"Estimating duration from bitrate, this may be inaccurate \n " );
2003-08-08 18:02:23 +00:00
}
2012-11-06 18:44:14 +01:00
#define DURATION_MAX_READ_SIZE 250000LL
2015-11-15 13:58:50 +01:00
#define DURATION_MAX_RETRY 6
2003-08-08 18:02:23 +00:00
/* only usable for MPEG-PS streams */
2011-07-15 20:27:43 +02:00
static void estimate_timings_from_pts ( AVFormatContext * ic , int64_t old_offset )
2003-08-08 18:02:23 +00:00
{
2021-01-31 13:05:49 -03:00
AVPacket * pkt = ic -> internal -> pkt ;
2003-08-08 18:02:23 +00:00
AVStream * st ;
2014-06-19 17:26:31 +00:00
int num , den , read_size , i , ret ;
2014-05-16 16:13:36 +02:00
int found_duration = 0 ;
int is_end ;
2003-08-08 18:02:23 +00:00
int64_t filesize , offset , duration ;
2014-01-16 01:53:03 +01:00
int retry = 0 ;
2005-12-17 18:14:38 +00:00
2007-04-26 10:49:48 +00:00
/* flush packet queue */
flush_packet_queue ( ic );
2014-01-16 01:53:03 +01:00
for ( i = 0 ; i < ic -> nb_streams ; i ++ ) {
2007-04-26 10:49:48 +00:00
st = ic -> streams [ i ];
2014-02-21 17:27:37 +01:00
if ( st -> start_time == AV_NOPTS_VALUE &&
2021-06-05 11:12:03 -03:00
st -> internal -> first_dts == AV_NOPTS_VALUE &&
2016-04-10 20:58:15 +01:00
st -> codecpar -> codec_type != AVMEDIA_TYPE_UNKNOWN )
2014-06-18 20:42:52 +02:00
av_log ( ic , AV_LOG_WARNING ,
2014-04-05 01:15:12 +02:00
"start time for stream %d is not set in estimate_timings_from_pts \n " , i );
2009-12-13 22:56:59 +00:00
2021-05-01 23:28:18 -03:00
if ( st -> internal -> parser ) {
av_parser_close ( st -> internal -> parser );
st -> internal -> parser = NULL ;
2007-04-26 10:49:48 +00:00
}
}
2005-12-17 18:14:38 +00:00
2018-05-15 15:56:45 -07:00
if ( ic -> skip_estimate_duration_from_pts ) {
av_log ( ic , AV_LOG_INFO , "Skipping duration calculation in estimate_timings_from_pts \n " );
goto skip_duration_calc ;
}
2014-07-11 16:42:52 +02:00
av_opt_set ( ic , "skip_changes" , "1" , AV_OPT_SEARCH_CHILDREN );
2003-08-08 18:02:23 +00:00
/* estimate the end time (duration) */
/* XXX: may need to support wrapping */
2011-10-09 14:12:14 +02:00
filesize = ic -> pb ? avio_size ( ic -> pb ) : 0 ;
2014-01-16 01:53:03 +01:00
do {
2014-05-16 16:13:36 +02:00
is_end = found_duration ;
2014-01-16 01:53:03 +01:00
offset = filesize - ( DURATION_MAX_READ_SIZE << retry );
2011-08-22 18:47:24 -07:00
if ( offset < 0 )
offset = 0 ;
2003-08-08 18:02:23 +00:00
2011-08-22 18:47:24 -07:00
avio_seek ( ic -> pb , offset , SEEK_SET );
read_size = 0 ;
2014-01-16 01:53:03 +01:00
for (;;) {
if ( read_size >= DURATION_MAX_READ_SIZE << ( FFMAX ( retry - 1 , 0 )))
2011-08-22 18:47:24 -07:00
break ;
2005-12-17 18:14:38 +00:00
2011-08-22 18:47:24 -07:00
do {
2012-03-04 21:41:59 +01:00
ret = ff_read_packet ( ic , pkt );
2014-01-16 01:53:03 +01:00
} while ( ret == AVERROR ( EAGAIN ));
2011-08-22 18:47:24 -07:00
if ( ret != 0 )
break ;
read_size += pkt -> size ;
2014-01-16 01:53:03 +01:00
st = ic -> streams [ pkt -> stream_index ];
2011-08-22 18:47:24 -07:00
if ( pkt -> pts != AV_NOPTS_VALUE &&
( st -> start_time != AV_NOPTS_VALUE ||
2021-06-05 11:12:03 -03:00
st -> internal -> first_dts != AV_NOPTS_VALUE )) {
2014-06-19 17:26:31 +00:00
if ( pkt -> duration == 0 ) {
2021-05-01 23:28:18 -03:00
ff_compute_frame_duration ( ic , & num , & den , st , st -> internal -> parser , pkt );
2014-06-19 17:26:31 +00:00
if ( den && num ) {
pkt -> duration = av_rescale_rnd ( 1 ,
num * ( int64_t ) st -> time_base . den ,
den * ( int64_t ) st -> time_base . num ,
AV_ROUND_DOWN );
}
}
2014-05-14 16:25:13 +00:00
duration = pkt -> pts + pkt -> duration ;
2014-05-16 16:13:36 +02:00
found_duration = 1 ;
2011-08-22 18:47:24 -07:00
if ( st -> start_time != AV_NOPTS_VALUE )
duration -= st -> start_time ;
else
2021-06-05 11:12:03 -03:00
duration -= st -> internal -> first_dts ;
2011-08-22 18:47:24 -07:00
if ( duration > 0 ) {
2020-10-09 08:15:27 +02:00
if ( st -> duration == AV_NOPTS_VALUE || st -> internal -> info -> last_duration <= 0 ||
( st -> duration < duration && FFABS ( duration - st -> internal -> info -> last_duration ) < 60LL * st -> time_base . den / st -> time_base . num ))
2011-08-22 18:47:24 -07:00
st -> duration = duration ;
2020-10-09 08:15:27 +02:00
st -> internal -> info -> last_duration = duration ;
2011-08-22 18:47:24 -07:00
}
2003-08-08 18:02:23 +00:00
}
2015-10-23 11:11:31 +02:00
av_packet_unref ( pkt );
2003-08-08 18:02:23 +00:00
}
2014-05-14 16:25:13 +00:00
/* check if all audio/video streams have valid duration */
2014-05-16 16:13:36 +02:00
if ( ! is_end ) {
is_end = 1 ;
for ( i = 0 ; i < ic -> nb_streams ; i ++ ) {
st = ic -> streams [ i ];
2016-04-10 20:58:15 +01:00
switch ( st -> codecpar -> codec_type ) {
2014-05-16 16:13:36 +02:00
case AVMEDIA_TYPE_VIDEO :
case AVMEDIA_TYPE_AUDIO :
if ( st -> duration == AV_NOPTS_VALUE )
is_end = 0 ;
}
2014-05-14 16:25:13 +00:00
}
}
2014-05-16 16:13:36 +02:00
} while ( ! is_end &&
2014-05-16 15:49:23 +02:00
offset &&
2014-01-16 01:53:03 +01:00
++ retry <= DURATION_MAX_RETRY );
2005-12-17 18:14:38 +00:00
2014-07-11 16:42:52 +02:00
av_opt_set ( ic , "skip_changes" , "0" , AV_OPT_SEARCH_CHILDREN );
2014-05-14 16:25:13 +00:00
/* warn about audio/video streams which duration could not be estimated */
for ( i = 0 ; i < ic -> nb_streams ; i ++ ) {
st = ic -> streams [ i ];
if ( st -> duration == AV_NOPTS_VALUE ) {
2016-04-10 20:58:15 +01:00
switch ( st -> codecpar -> codec_type ) {
2014-05-14 16:25:13 +00:00
case AVMEDIA_TYPE_VIDEO :
case AVMEDIA_TYPE_AUDIO :
2021-06-05 11:12:03 -03:00
if ( st -> start_time != AV_NOPTS_VALUE || st -> internal -> first_dts != AV_NOPTS_VALUE ) {
2019-09-26 13:16:24 +08:00
av_log ( ic , AV_LOG_WARNING , "stream %d : no PTS found at end of file, duration not set \n " , i );
2014-05-14 16:25:13 +00:00
} else
2019-09-26 13:16:24 +08:00
av_log ( ic , AV_LOG_WARNING , "stream %d : no TS found at start of file, duration not set \n " , i );
2014-05-14 16:25:13 +00:00
}
}
}
2018-05-15 15:56:45 -07:00
skip_duration_calc :
2005-04-30 21:43:59 +00:00
fill_all_stream_timings ( ic );
2003-08-08 18:02:23 +00:00
2011-02-28 14:57:54 +01:00
avio_seek ( ic -> pb , old_offset , SEEK_SET );
2014-01-16 01:53:03 +01:00
for ( i = 0 ; i < ic -> nb_streams ; i ++ ) {
2014-02-22 14:22:31 +01:00
int j ;
2014-01-16 01:53:03 +01:00
st = ic -> streams [ i ];
2021-06-05 11:12:03 -03:00
st -> internal -> cur_dts = st -> internal -> first_dts ;
2021-05-01 23:05:21 -03:00
st -> internal -> last_IP_pts = AV_NOPTS_VALUE ;
2020-10-09 09:22:36 +02:00
st -> internal -> last_dts_for_order_check = AV_NOPTS_VALUE ;
2014-02-22 14:22:31 +01:00
for ( j = 0 ; j < MAX_REORDER_DELAY + 1 ; j ++ )
2020-10-09 09:22:36 +02:00
st -> internal -> pts_buffer [ j ] = AV_NOPTS_VALUE ;
2007-08-18 00:44:14 +00:00
}
2003-08-08 18:02:23 +00:00
}
2019-09-29 11:58:43 +08:00
/* 1:1 map to AVDurationEstimationMethod */
2020-12-27 17:36:59 +01:00
static const char * const duration_name [] = {
2019-09-29 11:58:43 +08:00
[ AVFMT_DURATION_FROM_PTS ] = "pts" ,
[ AVFMT_DURATION_FROM_STREAM ] = "stream" ,
[ AVFMT_DURATION_FROM_BITRATE ] = "bit rate" ,
};
static const char * duration_estimate_name ( enum AVDurationEstimationMethod method )
{
return duration_name [ method ];
}
2011-07-15 20:27:43 +02:00
static void estimate_timings ( AVFormatContext * ic , int64_t old_offset )
2003-08-08 18:02:23 +00:00
{
int64_t file_size ;
/* get the file size, if possible */
if ( ic -> iformat -> flags & AVFMT_NOFILE ) {
file_size = 0 ;
} else {
2011-03-04 19:57:36 +01:00
file_size = avio_size ( ic -> pb );
2011-10-18 09:17:12 +02:00
file_size = FFMAX ( 0 , file_size );
2003-08-08 18:02:23 +00:00
}
2006-07-10 21:14:37 +00:00
if (( ! strcmp ( ic -> iformat -> name , "mpeg" ) ||
! strcmp ( ic -> iformat -> name , "mpegts" )) &&
2016-09-27 16:26:37 +02:00
file_size && ( ic -> pb -> seekable & AVIO_SEEKABLE_NORMAL )) {
2003-08-08 18:02:23 +00:00
/* get accurate estimate from the PTSes */
2011-07-15 20:27:43 +02:00
estimate_timings_from_pts ( ic , old_offset );
2012-06-17 22:20:09 -07:00
ic -> duration_estimation_method = AVFMT_DURATION_FROM_PTS ;
2011-07-15 20:27:43 +02:00
} else if ( has_duration ( ic )) {
2008-01-16 22:14:26 +00:00
/* at least one component has timings - we use them for all
2014-01-16 01:53:03 +01:00
* the components */
2003-08-08 18:02:23 +00:00
fill_all_stream_timings ( ic );
2019-09-28 10:45:31 +08:00
/* nut demuxer estimate the duration from PTS */
if ( ! strcmp ( ic -> iformat -> name , "nut" ))
ic -> duration_estimation_method = AVFMT_DURATION_FROM_PTS ;
else
ic -> duration_estimation_method = AVFMT_DURATION_FROM_STREAM ;
2003-08-08 18:02:23 +00:00
} else {
2008-01-16 22:14:26 +00:00
/* less precise: use bitrate info */
2011-07-15 20:27:43 +02:00
estimate_timings_from_bit_rate ( ic );
2012-06-17 22:20:09 -07:00
ic -> duration_estimation_method = AVFMT_DURATION_FROM_BITRATE ;
2003-08-08 18:02:23 +00:00
}
2011-07-15 20:27:43 +02:00
update_stream_timings ( ic );
2003-08-08 18:02:23 +00:00
2021-03-19 04:32:41 +01:00
for ( unsigned i = 0 ; i < ic -> nb_streams ; i ++ ) {
AVStream * st = ic -> streams [ i ];
if ( st -> time_base . den )
av_log ( ic , AV_LOG_TRACE , "stream %u: start_time: %s duration: %s \n " , i ,
av_ts2timestr ( st -> start_time , & st -> time_base ),
av_ts2timestr ( st -> duration , & st -> time_base ));
2003-08-08 18:02:23 +00:00
}
2021-03-19 04:32:41 +01:00
av_log ( ic , AV_LOG_TRACE ,
"format: start_time: %s duration: %s (estimate from %s) bitrate=%" PRId64 " kb/s \n " ,
av_ts2timestr ( ic -> start_time , & AV_TIME_BASE_Q ),
av_ts2timestr ( ic -> duration , & AV_TIME_BASE_Q ),
duration_estimate_name ( ic -> duration_estimation_method ),
( int64_t ) ic -> bit_rate / 1000 );
2003-08-08 18:02:23 +00:00
}
2012-07-16 00:27:09 +02:00
static int has_codec_parameters ( AVStream * st , const char ** errmsg_ptr )
2002-05-20 16:28:47 +00:00
{
2014-06-18 20:42:52 +02:00
AVCodecContext * avctx = st -> internal -> avctx ;
2012-07-16 00:27:09 +02:00
#define FAIL(errmsg) do { \
if (errmsg_ptr) \
*errmsg_ptr = errmsg; \
return 0; \
} while (0)
2014-06-01 19:40:56 +02:00
if ( avctx -> codec_id == AV_CODEC_ID_NONE
&& avctx -> codec_type != AVMEDIA_TYPE_DATA )
FAIL ( "unknown codec" );
2011-07-16 23:08:29 +02:00
switch ( avctx -> codec_type ) {
2010-03-30 23:30:55 +00:00
case AVMEDIA_TYPE_AUDIO :
2012-03-04 04:06:15 +01:00
if ( ! avctx -> frame_size && determinable_frame_size ( avctx ))
2012-09-07 14:27:47 +02:00
FAIL ( "unspecified frame size" );
2020-10-09 08:15:27 +02:00
if ( st -> internal -> info -> found_decoder >= 0 &&
2014-01-16 01:53:03 +01:00
avctx -> sample_fmt == AV_SAMPLE_FMT_NONE )
2012-07-16 00:27:09 +02:00
FAIL ( "unspecified sample format" );
if ( ! avctx -> sample_rate )
FAIL ( "unspecified sample rate" );
if ( ! avctx -> channels )
FAIL ( "unspecified number of channels" );
2020-10-09 09:22:36 +02:00
if ( st -> internal -> info -> found_decoder >= 0 && ! st -> internal -> nb_decoded_frames && avctx -> codec_id == AV_CODEC_ID_DTS )
2012-09-23 04:56:51 +02:00
FAIL ( "no decodable DTS frames" );
2002-05-20 16:28:47 +00:00
break ;
2010-03-30 23:30:55 +00:00
case AVMEDIA_TYPE_VIDEO :
2012-07-16 00:27:09 +02:00
if ( ! avctx -> width )
FAIL ( "unspecified size" );
2020-10-09 08:15:27 +02:00
if ( st -> internal -> info -> found_decoder >= 0 && avctx -> pix_fmt == AV_PIX_FMT_NONE )
2012-07-16 00:27:09 +02:00
FAIL ( "unspecified pixel format" );
2016-04-10 20:58:15 +01:00
if ( st -> codecpar -> codec_id == AV_CODEC_ID_RV30 || st -> codecpar -> codec_id == AV_CODEC_ID_RV40 )
2021-05-01 23:35:45 -03:00
if ( ! st -> sample_aspect_ratio . num && ! st -> codecpar -> sample_aspect_ratio . num && ! st -> internal -> codec_info_nb_frames )
2013-03-03 18:41:16 +01:00
FAIL ( "no frame in rv30/40 and no sar" );
2002-05-20 16:28:47 +00:00
break ;
2012-08-07 18:53:00 +02:00
case AVMEDIA_TYPE_SUBTITLE :
if ( avctx -> codec_id == AV_CODEC_ID_HDMV_PGS_SUBTITLE && ! avctx -> width )
FAIL ( "unspecified size" );
break ;
2011-08-26 17:39:11 -07:00
case AVMEDIA_TYPE_DATA :
2014-01-26 23:35:38 +01:00
if ( avctx -> codec_id == AV_CODEC_ID_NONE ) return 1 ;
2002-05-20 16:28:47 +00:00
}
2012-07-16 00:27:09 +02:00
return 1 ;
2002-05-20 16:28:47 +00:00
}
2012-01-18 10:59:32 +01:00
/* returns 1 or 0 if or if not decoded data was returned, or a negative error */
2019-09-20 22:39:10 +02:00
static int try_decode_frame ( AVFormatContext * s , AVStream * st ,
const AVPacket * avpkt , AVDictionary ** options )
2003-11-10 18:37:55 +00:00
{
2014-06-18 20:42:52 +02:00
AVCodecContext * avctx = st -> internal -> avctx ;
2012-08-18 13:22:38 +01:00
const AVCodec * codec ;
2012-01-02 09:01:02 +01:00
int got_picture = 1 , ret = 0 ;
2013-11-09 10:05:22 +01:00
AVFrame * frame = av_frame_alloc ();
2012-08-07 18:53:00 +02:00
AVSubtitle subtitle ;
2011-11-02 14:35:36 -04:00
AVPacket pkt = * avpkt ;
2015-11-24 14:14:54 +01:00
int do_skip_frame = 0 ;
enum AVDiscard skip_frame ;
2005-12-17 18:14:38 +00:00
2012-09-21 09:09:01 +02:00
if ( ! frame )
return AVERROR ( ENOMEM );
2016-04-10 20:58:15 +01:00
if ( ! avcodec_is_open ( avctx ) &&
2020-10-09 08:15:27 +02:00
st -> internal -> info -> found_decoder <= 0 &&
( st -> codecpar -> codec_id != - st -> internal -> info -> found_decoder || ! st -> codecpar -> codec_id )) {
2012-01-18 20:32:32 +01:00
AVDictionary * thread_opt = NULL ;
2016-09-21 19:00:46 +02:00
codec = find_probe_decoder ( s , st , st -> codecpar -> codec_id );
2012-01-28 19:15:15 +01:00
2012-02-27 18:02:10 -05:00
if ( ! codec ) {
2020-10-09 08:15:27 +02:00
st -> internal -> info -> found_decoder = - st -> codecpar -> codec_id ;
2014-01-16 01:53:03 +01:00
ret = - 1 ;
2012-09-21 09:09:01 +02:00
goto fail ;
2012-02-27 18:02:10 -05:00
}
2012-01-18 20:32:32 +01:00
2014-01-16 01:53:03 +01:00
/* Force thread count to 1 since the H.264 decoder will not extract
* SPS and PPS to extradata during multi-threaded decoding. */
2012-01-18 20:32:32 +01:00
av_dict_set ( options ? options : & thread_opt , "threads" , "1" , 0 );
2021-02-06 13:32:24 -03:00
/* Force lowres to 0. The decoder might reduce the video size by the
* lowres factor, and we don't want that propagated to the stream's
* codecpar */
av_dict_set ( options ? options : & thread_opt , "lowres" , "0" , 0 );
2014-09-30 23:25:39 +02:00
if ( s -> codec_whitelist )
av_dict_set ( options ? options : & thread_opt , "codec_whitelist" , s -> codec_whitelist , 0 );
2014-06-18 20:42:52 +02:00
ret = avcodec_open2 ( avctx , codec , options ? options : & thread_opt );
2012-01-18 20:32:32 +01:00
if ( ! options )
av_dict_free ( & thread_opt );
2012-02-27 18:02:10 -05:00
if ( ret < 0 ) {
2020-10-09 08:15:27 +02:00
st -> internal -> info -> found_decoder = - avctx -> codec_id ;
2012-09-21 09:09:01 +02:00
goto fail ;
2012-02-27 18:02:10 -05:00
}
2020-10-09 08:15:27 +02:00
st -> internal -> info -> found_decoder = 1 ;
} else if ( ! st -> internal -> info -> found_decoder )
st -> internal -> info -> found_decoder = 1 ;
2012-02-27 18:02:10 -05:00
2020-10-09 08:15:27 +02:00
if ( st -> internal -> info -> found_decoder < 0 ) {
2012-09-21 09:09:01 +02:00
ret = - 1 ;
goto fail ;
}
2005-04-25 18:29:06 +00:00
2016-04-21 13:35:22 +02:00
if ( avpriv_codec_get_cap_skip_frame_fill_param ( avctx -> codec )) {
2015-11-24 14:14:54 +01:00
do_skip_frame = 1 ;
2016-04-10 20:58:15 +01:00
skip_frame = avctx -> skip_frame ;
avctx -> skip_frame = AVDISCARD_ALL ;
2015-11-24 14:14:54 +01:00
}
2012-01-02 09:01:02 +01:00
while (( pkt . size > 0 || ( ! pkt . data && got_picture )) &&
ret >= 0 &&
2014-01-26 23:35:38 +01:00
( ! has_codec_parameters ( st , NULL ) || ! has_decode_delay_been_guessed ( st ) ||
2021-05-01 23:35:45 -03:00
( ! st -> internal -> codec_info_nb_frames &&
2014-06-18 20:42:52 +02:00
( avctx -> codec -> capabilities & AV_CODEC_CAP_CHANNEL_CONF )))) {
2011-11-02 14:35:36 -04:00
got_picture = 0 ;
2016-03-22 19:09:57 +01:00
if ( avctx -> codec_type == AVMEDIA_TYPE_VIDEO ||
avctx -> codec_type == AVMEDIA_TYPE_AUDIO ) {
ret = avcodec_send_packet ( avctx , & pkt );
if ( ret < 0 && ret != AVERROR ( EAGAIN ) && ret != AVERROR_EOF )
break ;
if ( ret >= 0 )
pkt . size = 0 ;
ret = avcodec_receive_frame ( avctx , frame );
if ( ret >= 0 )
got_picture = 1 ;
if ( ret == AVERROR ( EAGAIN ) || ret == AVERROR_EOF )
ret = 0 ;
} else if ( avctx -> codec_type == AVMEDIA_TYPE_SUBTITLE ) {
2016-04-10 20:58:15 +01:00
ret = avcodec_decode_subtitle2 ( avctx , & subtitle ,
2012-08-07 18:53:00 +02:00
& got_picture , & pkt );
2020-04-18 21:36:09 +02:00
if ( got_picture )
avsubtitle_free ( & subtitle );
2016-03-22 19:09:57 +01:00
if ( ret >= 0 )
pkt . size = 0 ;
2009-04-13 03:32:02 +00:00
}
2011-11-02 14:35:36 -04:00
if ( ret >= 0 ) {
if ( got_picture )
2020-10-09 09:22:36 +02:00
st -> internal -> nb_decoded_frames ++ ;
2012-01-18 10:59:32 +01:00
ret = got_picture ;
2011-11-02 14:35:36 -04:00
}
2003-11-10 18:37:55 +00:00
}
2012-09-21 09:09:01 +02:00
2014-01-26 23:35:38 +01:00
if ( ! pkt . data && ! got_picture )
2012-09-25 13:34:06 +02:00
ret = - 1 ;
2012-09-21 09:09:01 +02:00
fail :
2015-11-24 14:14:54 +01:00
if ( do_skip_frame ) {
2016-04-10 20:58:15 +01:00
avctx -> skip_frame = skip_frame ;
2015-11-24 14:14:54 +01:00
}
2013-11-29 21:41:52 +01:00
av_frame_free ( & frame );
2003-11-10 18:37:55 +00:00
return ret ;
}
2012-08-05 11:11:04 +02:00
unsigned int ff_codec_get_tag ( const AVCodecTag * tags , enum AVCodecID id )
2007-07-11 12:45:14 +00:00
{
2012-08-05 11:11:04 +02:00
while ( tags -> id != AV_CODEC_ID_NONE ) {
2007-07-11 12:45:14 +00:00
if ( tags -> id == id )
return tags -> tag ;
tags ++ ;
}
return 0 ;
}
2012-08-05 11:11:04 +02:00
enum AVCodecID ff_codec_get_id ( const AVCodecTag * tags , unsigned int tag )
2007-07-11 12:45:14 +00:00
{
2007-07-27 11:36:17 +00:00
int i ;
2014-01-16 01:53:03 +01:00
for ( i = 0 ; tags [ i ]. id != AV_CODEC_ID_NONE ; i ++ )
if ( tag == tags [ i ]. tag )
2007-07-27 11:36:17 +00:00
return tags [ i ]. id ;
2014-01-16 01:53:03 +01:00
for ( i = 0 ; tags [ i ]. id != AV_CODEC_ID_NONE ; i ++ )
2011-10-17 10:12:51 +02:00
if ( avpriv_toupper4 ( tag ) == avpriv_toupper4 ( tags [ i ]. tag ))
2007-07-27 11:36:17 +00:00
return tags [ i ]. id ;
2012-08-05 11:11:04 +02:00
return AV_CODEC_ID_NONE ;
2007-07-11 12:45:14 +00:00
}
2012-11-27 14:52:38 -05:00
enum AVCodecID ff_get_pcm_codec_id ( int bps , int flt , int be , int sflags )
{
2016-05-17 11:28:32 -07:00
if ( bps <= 0 || bps > 64 )
2016-05-11 00:00:52 +02:00
return AV_CODEC_ID_NONE ;
2012-11-27 14:52:38 -05:00
if ( flt ) {
switch ( bps ) {
2014-01-16 01:53:03 +01:00
case 32 :
return be ? AV_CODEC_ID_PCM_F32BE : AV_CODEC_ID_PCM_F32LE ;
case 64 :
return be ? AV_CODEC_ID_PCM_F64BE : AV_CODEC_ID_PCM_F64LE ;
default :
return AV_CODEC_ID_NONE ;
2012-11-27 14:52:38 -05:00
}
} else {
2012-11-29 13:58:57 +01:00
bps += 7 ;
2012-11-27 14:52:38 -05:00
bps >>= 3 ;
if ( sflags & ( 1 << ( bps - 1 ))) {
switch ( bps ) {
2014-01-16 01:53:03 +01:00
case 1 :
return AV_CODEC_ID_PCM_S8 ;
case 2 :
return be ? AV_CODEC_ID_PCM_S16BE : AV_CODEC_ID_PCM_S16LE ;
case 3 :
return be ? AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE ;
case 4 :
return be ? AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE ;
2016-08-17 19:46:21 +02:00
case 8 :
return be ? AV_CODEC_ID_PCM_S64BE : AV_CODEC_ID_PCM_S64LE ;
2014-01-16 01:53:03 +01:00
default :
return AV_CODEC_ID_NONE ;
2012-11-27 14:52:38 -05:00
}
} else {
switch ( bps ) {
2014-01-16 01:53:03 +01:00
case 1 :
return AV_CODEC_ID_PCM_U8 ;
case 2 :
return be ? AV_CODEC_ID_PCM_U16BE : AV_CODEC_ID_PCM_U16LE ;
case 3 :
return be ? AV_CODEC_ID_PCM_U24BE : AV_CODEC_ID_PCM_U24LE ;
case 4 :
return be ? AV_CODEC_ID_PCM_U32BE : AV_CODEC_ID_PCM_U32LE ;
default :
return AV_CODEC_ID_NONE ;
2012-11-27 14:52:38 -05:00
}
}
}
}
2014-01-16 01:53:03 +01:00
unsigned int av_codec_get_tag ( const AVCodecTag * const * tags , enum AVCodecID id )
2013-01-17 20:44:33 +01:00
{
unsigned int tag ;
if ( ! av_codec_get_tag2 ( tags , id , & tag ))
return 0 ;
return tag ;
}
int av_codec_get_tag2 ( const AVCodecTag * const * tags , enum AVCodecID id ,
unsigned int * tag )
2007-07-11 12:45:14 +00:00
{
int i ;
2014-01-16 01:53:03 +01:00
for ( i = 0 ; tags && tags [ i ]; i ++ ) {
2013-01-17 20:44:33 +01:00
const AVCodecTag * codec_tags = tags [ i ];
while ( codec_tags -> id != AV_CODEC_ID_NONE ) {
if ( codec_tags -> id == id ) {
* tag = codec_tags -> tag ;
return 1 ;
}
codec_tags ++ ;
}
2007-07-11 12:45:14 +00:00
}
return 0 ;
}
2014-01-16 01:53:03 +01:00
enum AVCodecID av_codec_get_id ( const AVCodecTag * const * tags , unsigned int tag )
2007-07-11 12:45:14 +00:00
{
int i ;
2014-01-16 01:53:03 +01:00
for ( i = 0 ; tags && tags [ i ]; i ++ ) {
enum AVCodecID id = ff_codec_get_id ( tags [ i ], tag );
if ( id != AV_CODEC_ID_NONE )
return id ;
2007-07-11 12:45:14 +00:00
}
2012-08-05 11:11:04 +02:00
return AV_CODEC_ID_NONE ;
2007-07-11 12:45:14 +00:00
}
2020-11-21 14:51:25 +01:00
static int chapter_start_cmp ( const void * p1 , const void * p2 )
2008-05-24 21:44:29 +00:00
{
2020-11-21 14:51:25 +01:00
AVChapter * ch1 = * ( AVChapter ** ) p1 ;
AVChapter * ch2 = * ( AVChapter ** ) p2 ;
int delta = av_compare_ts ( ch1 -> start , ch1 -> time_base , ch2 -> start , ch2 -> time_base );
if ( delta )
return delta ;
return ( ch1 > ch2 ) - ( ch1 < ch2 );
}
static int compute_chapters_end ( AVFormatContext * s )
{
unsigned int i ;
2015-12-02 22:59:56 +01:00
int64_t max_time = 0 ;
2020-11-21 14:51:25 +01:00
AVChapter ** timetable = av_malloc ( s -> nb_chapters * sizeof ( * timetable ));
if ( ! timetable )
return AVERROR ( ENOMEM );
2015-12-02 22:59:56 +01:00
2016-05-28 23:51:35 +02:00
if ( s -> duration > 0 && s -> start_time < INT64_MAX - s -> duration )
2015-12-02 22:59:56 +01:00
max_time = s -> duration +
2014-01-16 01:53:03 +01:00
(( s -> start_time == AV_NOPTS_VALUE ) ? 0 : s -> start_time );
2008-05-24 21:44:29 +00:00
2011-04-01 03:02:02 +02:00
for ( i = 0 ; i < s -> nb_chapters ; i ++ )
2020-11-21 14:51:25 +01:00
timetable [ i ] = s -> chapters [ i ];
qsort ( timetable , s -> nb_chapters , sizeof ( * timetable ), chapter_start_cmp );
2008-05-24 21:44:29 +00:00
2020-11-21 14:51:25 +01:00
for ( i = 0 ; i < s -> nb_chapters ; i ++ )
if ( timetable [ i ] -> end == AV_NOPTS_VALUE ) {
AVChapter * ch = timetable [ i ];
int64_t end = max_time ? av_rescale_q ( max_time , AV_TIME_BASE_Q ,
ch -> time_base )
: INT64_MAX ;
if ( i + 1 < s -> nb_chapters ) {
AVChapter * ch1 = timetable [ i + 1 ];
2014-01-16 01:53:03 +01:00
int64_t next_start = av_rescale_q ( ch1 -> start , ch1 -> time_base ,
2020-11-21 14:51:25 +01:00
ch -> time_base );
if ( next_start > ch -> start && next_start < end )
2011-04-01 03:02:02 +02:00
end = next_start ;
}
2017-09-17 23:34:58 +02:00
ch -> end = ( end == INT64_MAX || end < ch -> start ) ? ch -> start : end ;
2011-04-01 03:02:02 +02:00
}
2020-11-21 14:51:25 +01:00
av_free ( timetable );
return 0 ;
2008-05-24 21:44:29 +00:00
}
2014-01-16 01:53:03 +01:00
static int get_std_framerate ( int i )
{
2014-11-21 12:37:59 +01:00
if ( i < 30 * 12 )
2014-01-26 23:35:38 +01:00
return ( i + 1 ) * 1001 ;
2014-11-21 12:37:59 +01:00
i -= 30 * 12 ;
2016-01-09 10:49:23 +01:00
if ( i < 30 )
return ( i + 31 ) * 1001 * 12 ;
i -= 30 ;
2014-11-21 12:37:59 +01:00
2016-01-09 10:49:23 +01:00
if ( i < 3 )
return (( const int []) { 80 , 120 , 240 })[ i ] * 1001 * 12 ;
i -= 3 ;
2014-11-21 12:37:59 +01:00
return (( const int []) { 24 , 30 , 60 , 12 , 15 , 48 })[ i ] * 1000 * 12 ;
2006-12-11 16:59:10 +00:00
}
2014-01-16 01:53:03 +01:00
/* Is the time base unreliable?
2007-12-27 00:16:48 +00:00
* This is a heuristic to balance between quick acceptance of the values in
* the headers vs. some extra checks.
2008-01-16 22:14:26 +00:00
* Old DivX and Xvid often have nonsense timebases like 1fps or 2fps.
* MPEG-2 commonly misuses field repeat flags to store different framerates.
2014-01-16 01:53:03 +01:00
* And there are "variable" fps files this needs to detect as well. */
static int tb_unreliable ( AVCodecContext * c )
{
2015-02-01 19:19:25 +01:00
if ( c -> time_base . den >= 101LL * c -> time_base . num ||
c -> time_base . den < 5LL * c -> time_base . num ||
2014-01-16 01:53:03 +01:00
// c->codec_tag == AV_RL32("DIVX") ||
// c->codec_tag == AV_RL32("XVID") ||
2014-01-26 23:35:38 +01:00
c -> codec_tag == AV_RL32 ( "mp4v" ) ||
2014-01-16 01:53:03 +01:00
c -> codec_id == AV_CODEC_ID_MPEG2VIDEO ||
2014-04-28 15:14:41 +02:00
c -> codec_id == AV_CODEC_ID_GIF ||
2015-04-18 00:59:58 +02:00
c -> codec_id == AV_CODEC_ID_HEVC ||
2014-01-16 01:53:03 +01:00
c -> codec_id == AV_CODEC_ID_H264 )
2007-12-27 00:16:48 +00:00
return 1 ;
return 0 ;
}
2016-04-10 20:58:15 +01:00
int ff_alloc_extradata ( AVCodecParameters * par , int size )
2013-10-13 10:19:09 +00:00
{
2018-03-06 01:19:13 -03:00
av_freep ( & par -> extradata );
2018-03-06 01:37:21 -03:00
par -> extradata_size = 0 ;
if ( size < 0 || size >= INT32_MAX - AV_INPUT_BUFFER_PADDING_SIZE )
2013-10-13 10:19:09 +00:00
return AVERROR ( EINVAL );
2018-03-06 01:37:21 -03:00
2016-04-10 20:58:15 +01:00
par -> extradata = av_malloc ( size + AV_INPUT_BUFFER_PADDING_SIZE );
2018-03-06 01:37:21 -03:00
if ( ! par -> extradata )
return AVERROR ( ENOMEM );
memset ( par -> extradata + size , 0 , AV_INPUT_BUFFER_PADDING_SIZE );
par -> extradata_size = size ;
return 0 ;
2013-10-13 10:19:09 +00:00
}
2016-04-14 18:21:08 +02:00
int ff_get_extradata ( AVFormatContext * s , AVCodecParameters * par , AVIOContext * pb , int size )
2013-12-25 16:34:46 +01:00
{
2016-04-10 20:58:15 +01:00
int ret = ff_alloc_extradata ( par , size );
2013-12-25 16:34:46 +01:00
if ( ret < 0 )
return ret ;
2021-08-06 22:47:22 +02:00
ret = ffio_read_size ( pb , par -> extradata , size );
if ( ret < 0 ) {
2016-04-10 20:58:15 +01:00
av_freep ( & par -> extradata );
par -> extradata_size = 0 ;
2016-04-14 18:21:08 +02:00
av_log ( s , AV_LOG_ERROR , "Failed to read extradata of size %d \n " , size );
2021-08-06 22:47:22 +02:00
return ret ;
2013-12-25 16:34:46 +01:00
}
return ret ;
}
2013-12-05 16:56:17 +01:00
int ff_rfps_add_frame ( AVFormatContext * ic , AVStream * st , int64_t ts )
{
int i , j ;
2020-10-09 08:15:27 +02:00
int64_t last = st -> internal -> info -> last_dts ;
2013-12-05 16:56:17 +01:00
2014-01-26 23:35:38 +01:00
if ( ts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && ts > last
&& ts - ( uint64_t ) last < INT64_MAX ) {
double dts = ( is_relative ( ts ) ? ts - RELATIVE_TS_BASE : ts ) * av_q2d ( st -> time_base );
int64_t duration = ts - last ;
2013-12-05 16:56:17 +01:00
2020-10-09 08:15:27 +02:00
if ( ! st -> internal -> info -> duration_error )
st -> internal -> info -> duration_error = av_mallocz ( sizeof ( st -> internal -> info -> duration_error [ 0 ]) * 2 );
if ( ! st -> internal -> info -> duration_error )
2013-12-05 16:56:17 +01:00
return AVERROR ( ENOMEM );
2014-01-26 23:35:38 +01:00
// if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
2013-12-05 16:56:17 +01:00
// av_log(NULL, AV_LOG_ERROR, "%f\n", dts);
2014-01-26 23:35:38 +01:00
for ( i = 0 ; i < MAX_STD_TIMEBASES ; i ++ ) {
2020-10-09 08:15:27 +02:00
if ( st -> internal -> info -> duration_error [ 0 ][ 1 ][ i ] < 1e10 ) {
2014-01-26 23:35:38 +01:00
int framerate = get_std_framerate ( i );
double sdts = dts * framerate / ( 1001 * 12 );
for ( j = 0 ; j < 2 ; j ++ ) {
int64_t ticks = llrint ( sdts + j * 0.5 );
2013-12-07 04:13:44 +01:00
double error = sdts - ticks + j * 0.5 ;
2020-10-09 08:15:27 +02:00
st -> internal -> info -> duration_error [ j ][ 0 ][ i ] += error ;
st -> internal -> info -> duration_error [ j ][ 1 ][ i ] += error * error ;
2013-12-07 04:13:44 +01:00
}
2013-12-05 16:56:17 +01:00
}
}
2020-10-09 08:15:27 +02:00
if ( st -> internal -> info -> rfps_duration_sum <= INT64_MAX - duration ) {
st -> internal -> info -> duration_count ++ ;
st -> internal -> info -> rfps_duration_sum += duration ;
2019-07-04 23:01:19 +02:00
}
2013-12-07 04:13:44 +01:00
2020-10-09 08:15:27 +02:00
if ( st -> internal -> info -> duration_count % 10 == 0 ) {
int n = st -> internal -> info -> duration_count ;
2014-01-26 23:35:38 +01:00
for ( i = 0 ; i < MAX_STD_TIMEBASES ; i ++ ) {
2020-10-09 08:15:27 +02:00
if ( st -> internal -> info -> duration_error [ 0 ][ 1 ][ i ] < 1e10 ) {
double a0 = st -> internal -> info -> duration_error [ 0 ][ 0 ][ i ] / n ;
double error0 = st -> internal -> info -> duration_error [ 0 ][ 1 ][ i ] / n - a0 * a0 ;
double a1 = st -> internal -> info -> duration_error [ 1 ][ 0 ][ i ] / n ;
double error1 = st -> internal -> info -> duration_error [ 1 ][ 1 ][ i ] / n - a1 * a1 ;
2013-12-07 04:13:44 +01:00
if ( error0 > 0.04 && error1 > 0.04 ) {
2020-10-09 08:15:27 +02:00
st -> internal -> info -> duration_error [ 0 ][ 1 ][ i ] = 2e10 ;
st -> internal -> info -> duration_error [ 1 ][ 1 ][ i ] = 2e10 ;
2013-12-07 04:13:44 +01:00
}
}
}
}
2013-12-05 16:56:17 +01:00
// ignore the first 4 values, they might have some random jitter
2020-10-09 08:15:27 +02:00
if ( st -> internal -> info -> duration_count > 3 && is_relative ( ts ) == is_relative ( last ))
st -> internal -> info -> duration_gcd = av_gcd ( st -> internal -> info -> duration_gcd , duration );
2013-12-05 16:56:17 +01:00
}
if ( ts != AV_NOPTS_VALUE )
2020-10-09 08:15:27 +02:00
st -> internal -> info -> last_dts = ts ;
2013-12-05 16:56:17 +01:00
return 0 ;
}
void ff_rfps_calculate ( AVFormatContext * ic )
{
int i , j ;
2014-01-26 23:35:38 +01:00
for ( i = 0 ; i < ic -> nb_streams ; i ++ ) {
2013-12-05 16:56:17 +01:00
AVStream * st = ic -> streams [ i ];
2016-04-10 20:58:15 +01:00
if ( st -> codecpar -> codec_type != AVMEDIA_TYPE_VIDEO )
2013-12-05 16:56:17 +01:00
continue ;
// the check for tb_unreliable() is not completely correct, since this is not about handling
2016-03-28 14:07:47 -08:00
// an unreliable/inexact time base, but a time base that is finer than necessary, as e.g.
2013-12-05 16:56:17 +01:00
// ipmovie.c produces.
2021-03-04 00:15:53 +01:00
if ( tb_unreliable ( st -> internal -> avctx ) && st -> internal -> info -> duration_count > 15 && st -> internal -> info -> duration_gcd > FFMAX ( 1 , st -> time_base . den / ( 500LL * st -> time_base . num )) && ! st -> r_frame_rate . num &&
st -> internal -> info -> duration_gcd < INT64_MAX / st -> time_base . num )
2020-10-09 08:15:27 +02:00
av_reduce ( & st -> r_frame_rate . num , & st -> r_frame_rate . den , st -> time_base . den , st -> time_base . num * st -> internal -> info -> duration_gcd , INT_MAX );
if ( st -> internal -> info -> duration_count > 1 && ! st -> r_frame_rate . num
2016-04-10 20:58:15 +01:00
&& tb_unreliable ( st -> internal -> avctx )) {
2013-12-05 16:56:17 +01:00
int num = 0 ;
double best_error = 0.01 ;
2014-04-28 15:40:23 +02:00
AVRational ref_rate = st -> r_frame_rate . num ? st -> r_frame_rate : av_inv_q ( st -> time_base );
2013-12-05 16:56:17 +01:00
2014-01-26 23:35:38 +01:00
for ( j = 0 ; j < MAX_STD_TIMEBASES ; j ++ ) {
2013-12-05 16:56:17 +01:00
int k ;
2020-10-09 08:15:27 +02:00
if ( st -> internal -> info -> codec_info_duration &&
st -> internal -> info -> codec_info_duration * av_q2d ( st -> time_base ) < ( 1001 * 11.5 ) / get_std_framerate ( j ))
2013-12-05 16:56:17 +01:00
continue ;
2020-10-09 08:15:27 +02:00
if ( ! st -> internal -> info -> codec_info_duration && get_std_framerate ( j ) < 1001 * 12 )
2013-12-05 16:56:17 +01:00
continue ;
2013-12-15 21:40:13 +01:00
2020-10-09 08:15:27 +02:00
if ( av_q2d ( st -> time_base ) * st -> internal -> info -> rfps_duration_sum / st -> internal -> info -> duration_count < ( 1001 * 12.0 * 0.8 ) / get_std_framerate ( j ))
2013-12-15 21:40:13 +01:00
continue ;
2014-01-26 23:35:38 +01:00
for ( k = 0 ; k < 2 ; k ++ ) {
2020-10-09 08:15:27 +02:00
int n = st -> internal -> info -> duration_count ;
double a = st -> internal -> info -> duration_error [ k ][ 0 ][ j ] / n ;
double error = st -> internal -> info -> duration_error [ k ][ 1 ][ j ] / n - a * a ;
2013-12-05 16:56:17 +01:00
2014-01-26 23:35:38 +01:00
if ( error < best_error && best_error > 0.000000001 ) {
2013-12-05 16:56:17 +01:00
best_error = error ;
num = get_std_framerate ( j );
}
2014-01-26 23:35:38 +01:00
if ( error < 0.02 )
2015-04-20 16:23:43 +02:00
av_log ( ic , AV_LOG_DEBUG , "rfps: %f %f \n " , get_std_framerate ( j ) / 12.0 / 1001 , error );
2013-12-05 16:56:17 +01:00
}
}
// do not increase frame rate by more than 1 % in order to match a standard rate.
2014-04-28 15:40:23 +02:00
if ( num && ( ! ref_rate . num || ( double ) num / ( 12 * 1001 ) < 1.01 * av_q2d ( ref_rate )))
2013-12-05 16:56:17 +01:00
av_reduce ( & st -> r_frame_rate . num , & st -> r_frame_rate . den , num , 12 * 1001 , INT_MAX );
}
2014-04-28 18:04:38 +02:00
if ( ! st -> avg_frame_rate . num
2020-10-09 08:15:27 +02:00
&& st -> r_frame_rate . num && st -> internal -> info -> rfps_duration_sum
&& st -> internal -> info -> codec_info_duration <= 0
&& st -> internal -> info -> duration_count > 2
&& fabs ( 1.0 / ( av_q2d ( st -> r_frame_rate ) * av_q2d ( st -> time_base )) - st -> internal -> info -> rfps_duration_sum / ( double ) st -> internal -> info -> duration_count ) <= 1.0
2014-04-28 18:04:38 +02:00
) {
av_log ( ic , AV_LOG_DEBUG , "Setting avg frame rate based on r frame rate \n " );
st -> avg_frame_rate = st -> r_frame_rate ;
}
2013-12-05 16:56:17 +01:00
2020-10-09 08:15:27 +02:00
av_freep ( & st -> internal -> info -> duration_error );
st -> internal -> info -> last_dts = AV_NOPTS_VALUE ;
st -> internal -> info -> duration_count = 0 ;
st -> internal -> info -> rfps_duration_sum = 0 ;
2013-12-05 16:56:17 +01:00
}
}
2017-03-24 18:42:19 -03:00
static int extract_extradata_check ( AVStream * st )
{
const AVBitStreamFilter * f ;
f = av_bsf_get_by_name ( "extract_extradata" );
if ( ! f )
return 0 ;
if ( f -> codec_ids ) {
const enum AVCodecID * ids ;
for ( ids = f -> codec_ids ; * ids != AV_CODEC_ID_NONE ; ids ++ )
if ( * ids == st -> codecpar -> codec_id )
return 1 ;
}
return 0 ;
}
static int extract_extradata_init ( AVStream * st )
{
2018-09-27 00:00:25 +02:00
AVStreamInternal * sti = st -> internal ;
2017-03-24 18:42:19 -03:00
const AVBitStreamFilter * f ;
int ret ;
f = av_bsf_get_by_name ( "extract_extradata" );
if ( ! f )
goto finish ;
/* check that the codec id is supported */
ret = extract_extradata_check ( st );
if ( ! ret )
goto finish ;
2018-09-27 00:00:25 +02:00
ret = av_bsf_alloc ( f , & sti -> extract_extradata . bsf );
2017-03-24 18:42:19 -03:00
if ( ret < 0 )
2021-03-18 05:23:54 +01:00
return ret ;
2017-03-24 18:42:19 -03:00
2018-09-27 00:00:25 +02:00
ret = avcodec_parameters_copy ( sti -> extract_extradata . bsf -> par_in ,
2017-03-24 18:42:19 -03:00
st -> codecpar );
if ( ret < 0 )
goto fail ;
2018-09-27 00:00:25 +02:00
sti -> extract_extradata . bsf -> time_base_in = st -> time_base ;
2017-03-24 18:42:19 -03:00
2018-09-27 00:00:25 +02:00
ret = av_bsf_init ( sti -> extract_extradata . bsf );
2018-09-27 00:00:24 +02:00
if ( ret < 0 )
goto fail ;
2017-03-24 18:42:19 -03:00
finish :
2018-09-27 00:00:25 +02:00
sti -> extract_extradata . inited = 1 ;
2017-03-24 18:42:19 -03:00
return 0 ;
fail :
2018-09-27 00:00:25 +02:00
av_bsf_free ( & sti -> extract_extradata . bsf );
2017-03-24 18:42:19 -03:00
return ret ;
}
2021-03-18 05:23:54 +01:00
static int extract_extradata ( AVFormatContext * s , AVStream * st , const AVPacket * pkt )
2017-03-24 18:42:19 -03:00
{
2018-09-27 00:00:25 +02:00
AVStreamInternal * sti = st -> internal ;
2021-03-18 05:23:54 +01:00
AVPacket * pkt_ref = s -> internal -> parse_pkt ;
2017-03-24 18:42:19 -03:00
int ret ;
2018-09-27 00:00:25 +02:00
if ( ! sti -> extract_extradata . inited ) {
2017-03-24 18:42:19 -03:00
ret = extract_extradata_init ( st );
if ( ret < 0 )
return ret ;
}
2018-09-27 00:00:25 +02:00
if ( sti -> extract_extradata . inited && ! sti -> extract_extradata . bsf )
2017-03-24 18:42:19 -03:00
return 0 ;
ret = av_packet_ref ( pkt_ref , pkt );
if ( ret < 0 )
return ret ;
2018-09-27 00:00:25 +02:00
ret = av_bsf_send_packet ( sti -> extract_extradata . bsf , pkt_ref );
2017-03-24 18:42:19 -03:00
if ( ret < 0 ) {
av_packet_unref ( pkt_ref );
return ret ;
}
2018-09-27 00:00:25 +02:00
while ( ret >= 0 && ! sti -> avctx -> extradata ) {
ret = av_bsf_receive_packet ( sti -> extract_extradata . bsf , pkt_ref );
2017-03-24 18:42:19 -03:00
if ( ret < 0 ) {
if ( ret != AVERROR ( EAGAIN ) && ret != AVERROR_EOF )
return ret ;
continue ;
}
2020-09-07 15:47:07 +02:00
for ( int i = 0 ; i < pkt_ref -> side_data_elems ; i ++ ) {
AVPacketSideData * side_data = & pkt_ref -> side_data [ i ];
if ( side_data -> type == AV_PKT_DATA_NEW_EXTRADATA ) {
sti -> avctx -> extradata = side_data -> data ;
sti -> avctx -> extradata_size = side_data -> size ;
side_data -> data = NULL ;
side_data -> size = 0 ;
break ;
2017-03-24 18:42:19 -03:00
}
}
av_packet_unref ( pkt_ref );
}
return 0 ;
}
2020-03-05 09:17:22 +01:00
static int add_coded_side_data ( AVStream * st , AVCodecContext * avctx )
{
int i ;
for ( i = 0 ; i < avctx -> nb_coded_side_data ; i ++ ) {
const AVPacketSideData * sd_src = & avctx -> coded_side_data [ i ];
uint8_t * dst_data ;
dst_data = av_stream_new_side_data ( st , sd_src -> type , sd_src -> size );
if ( ! dst_data )
return AVERROR ( ENOMEM );
memcpy ( dst_data , sd_src -> data , sd_src -> size );
}
return 0 ;
}
2011-05-22 19:24:59 +02:00
int avformat_find_stream_info ( AVFormatContext * ic , AVDictionary ** options )
2002-05-20 16:28:47 +00:00
{
2016-05-26 17:09:44 +02:00
int i , count = 0 , ret = 0 , j ;
2013-03-20 17:23:23 +01:00
int64_t read_size ;
2002-05-20 16:28:47 +00:00
AVStream * st ;
2014-06-18 20:42:52 +02:00
AVCodecContext * avctx ;
2021-01-31 13:05:49 -03:00
AVPacket * pkt1 = ic -> internal -> pkt ;
2014-01-16 01:53:03 +01:00
int64_t old_offset = avio_tell ( ic -> pb );
// new streams might appear, no options for those
int orig_nb_streams = ic -> nb_streams ;
2014-07-30 11:09:25 +02:00
int flush_codecs ;
2015-09-01 09:19:49 +02:00
int64_t max_analyze_duration = ic -> max_analyze_duration ;
2014-12-01 15:26:58 +01:00
int64_t max_stream_analyze_duration ;
2015-07-16 03:37:43 +02:00
int64_t max_subtitle_analyze_duration ;
2015-09-01 09:19:49 +02:00
int64_t probesize = ic -> probesize ;
2016-03-12 02:40:25 -08:00
int eof_reached = 0 ;
2016-11-27 03:39:20 +01:00
int * missing_streams = av_opt_ptr ( ic -> iformat -> priv_class , ic -> priv_data , "missing_streams" );
2014-07-30 11:09:25 +02:00
flush_codecs = probesize > 0 ;
2014-06-02 21:21:11 +02:00
2014-07-12 21:49:15 +02:00
av_opt_set ( ic , "skip_clear" , "1" , AV_OPT_SEARCH_CHILDREN );
2014-12-01 15:26:58 +01:00
max_stream_analyze_duration = max_analyze_duration ;
2015-07-16 03:37:43 +02:00
max_subtitle_analyze_duration = max_analyze_duration ;
2014-06-02 21:21:11 +02:00
if ( ! max_analyze_duration ) {
2014-12-01 15:26:58 +01:00
max_stream_analyze_duration =
max_analyze_duration = 5 * AV_TIME_BASE ;
2015-07-16 03:37:43 +02:00
max_subtitle_analyze_duration = 30 * AV_TIME_BASE ;
2014-12-01 15:26:58 +01:00
if ( ! strcmp ( ic -> iformat -> name , "flv" ))
2015-09-11 00:58:37 +02:00
max_stream_analyze_duration = 90 * AV_TIME_BASE ;
2016-03-19 21:11:58 +01:00
if ( ! strcmp ( ic -> iformat -> name , "mpeg" ) || ! strcmp ( ic -> iformat -> name , "mpegts" ))
max_stream_analyze_duration = 7 * AV_TIME_BASE ;
2014-06-02 21:21:11 +02:00
}
2007-03-02 13:23:06 +00:00
2021-08-04 16:52:07 +02:00
if ( ic -> pb ) {
FFIOContext * const ctx = ffiocontext ( ic -> pb );
2016-06-14 11:08:54 -07:00
av_log ( ic , AV_LOG_DEBUG , "Before avformat_find_stream_info() pos: %" PRId64 " bytes read:%" PRId64 " seeks:%d nb_streams:%d \n " ,
2021-08-04 16:52:07 +02:00
avio_tell ( ic -> pb ), ctx -> bytes_read , ctx -> seek_count , ic -> nb_streams );
}
2012-04-14 10:43:35 +02:00
2014-01-16 01:53:03 +01:00
for ( i = 0 ; i < ic -> nb_streams ; i ++ ) {
2012-08-18 13:22:38 +01:00
const AVCodec * codec ;
2012-01-18 20:32:32 +01:00
AVDictionary * thread_opt = NULL ;
2005-04-30 21:43:59 +00:00
st = ic -> streams [ i ];
2014-06-18 20:42:52 +02:00
avctx = st -> internal -> avctx ;
2011-06-27 23:39:12 -07:00
2016-04-10 20:58:15 +01:00
if ( st -> codecpar -> codec_type == AVMEDIA_TYPE_VIDEO ||
st -> codecpar -> codec_type == AVMEDIA_TYPE_SUBTITLE ) {
2014-01-26 23:35:38 +01:00
/* if (!st->time_base.num)
st->time_base = */
2016-04-10 20:58:15 +01:00
if ( ! avctx -> time_base . num )
avctx -> time_base = st -> time_base ;
2005-04-30 21:43:59 +00:00
}
2016-10-08 17:49:10 +02:00
/* check if the caller has overridden the codec id */
2014-01-16 01:53:03 +01:00
// only for the split stuff
2021-05-01 23:28:18 -03:00
if ( ! st -> internal -> parser && ! ( ic -> flags & AVFMT_FLAG_NOPARSE ) && st -> internal -> request_probe <= 0 ) {
st -> internal -> parser = av_parser_init ( st -> codecpar -> codec_id );
if ( st -> internal -> parser ) {
if ( st -> internal -> need_parsing == AVSTREAM_PARSE_HEADERS ) {
st -> internal -> parser -> flags |= PARSER_FLAG_COMPLETE_FRAMES ;
} else if ( st -> internal -> need_parsing == AVSTREAM_PARSE_FULL_RAW ) {
st -> internal -> parser -> flags |= PARSER_FLAG_USE_CODEC_TS ;
2012-05-21 14:32:24 +02:00
}
2021-05-01 23:28:18 -03:00
} else if ( st -> internal -> need_parsing ) {
2012-06-07 19:02:32 +02:00
av_log ( ic , AV_LOG_VERBOSE , "parser not found for codec "
"%s, packets or times may be invalid. \n " ,
2016-04-10 20:58:15 +01:00
avcodec_get_name ( st -> codecpar -> codec_id ));
2005-08-15 15:58:21 +00:00
}
2005-06-27 00:04:03 +00:00
}
2014-06-18 20:42:52 +02:00
ret = avcodec_parameters_to_context ( avctx , st -> codecpar );
if ( ret < 0 )
goto find_stream_info_err ;
2020-10-09 09:22:36 +02:00
if ( st -> internal -> request_probe <= 0 )
2014-06-18 20:42:52 +02:00
st -> internal -> avctx_inited = 1 ;
2016-09-21 19:00:46 +02:00
codec = find_probe_decoder ( ic , st , st -> codecpar -> codec_id );
2010-10-02 22:18:02 +00:00
2014-01-16 01:53:03 +01:00
/* Force thread count to 1 since the H.264 decoder will not extract
* SPS and PPS to extradata during multi-threaded decoding. */
2012-01-18 20:32:32 +01:00
av_dict_set ( options ? & options [ i ] : & thread_opt , "threads" , "1" , 0 );
2021-02-06 13:32:24 -03:00
/* Force lowres to 0. The decoder might reduce the video size by the
* lowres factor, and we don't want that propagated to the stream's
* codecpar */
av_dict_set ( options ? & options [ i ] : & thread_opt , "lowres" , "0" , 0 );
2012-01-07 15:36:44 +01:00
2014-09-30 23:25:39 +02:00
if ( ic -> codec_whitelist )
av_dict_set ( options ? & options [ i ] : & thread_opt , "codec_whitelist" , ic -> codec_whitelist , 0 );
2014-01-16 01:53:03 +01:00
// Try to just open decoders, in case this is enough to get parameters.
2021-04-14 21:56:50 +02:00
// Also ensure that subtitle_header is properly set.
if ( ! has_codec_parameters ( st , NULL ) && st -> internal -> request_probe <= 0 ||
st -> codecpar -> codec_type == AVMEDIA_TYPE_SUBTITLE ) {
2014-06-18 20:42:52 +02:00
if ( codec && ! avctx -> codec )
2016-04-10 20:58:15 +01:00
if ( avcodec_open2 ( avctx , codec , options ? & options [ i ] : & thread_opt ) < 0 )
2014-01-26 23:35:38 +01:00
av_log ( ic , AV_LOG_WARNING ,
2016-12-05 15:17:13 +08:00
"Failed to open codec in %s \n " , __FUNCTION__ );
2010-02-03 23:05:58 +00:00
}
2012-01-18 20:32:32 +01:00
if ( ! options )
av_dict_free ( & thread_opt );
2005-04-30 21:43:59 +00:00
}
2014-01-16 01:53:03 +01:00
for ( i = 0 ; i < ic -> nb_streams ; i ++ ) {
2012-06-26 13:10:01 +02:00
#if FF_API_R_FRAME_RATE
2020-10-09 08:15:27 +02:00
ic -> streams [ i ] -> internal -> info -> last_dts = AV_NOPTS_VALUE ;
2012-06-26 13:10:01 +02:00
#endif
2020-10-09 08:15:27 +02:00
ic -> streams [ i ] -> internal -> info -> fps_first_dts = AV_NOPTS_VALUE ;
ic -> streams [ i ] -> internal -> info -> fps_last_dts = AV_NOPTS_VALUE ;
2004-12-19 01:23:22 +00:00
}
2005-12-17 18:14:38 +00:00
2002-05-20 16:28:47 +00:00
read_size = 0 ;
2014-01-16 01:53:03 +01:00
for (;;) {
2019-09-20 22:39:10 +02:00
const AVPacket * pkt ;
2014-12-01 15:26:58 +01:00
int analyzed_all_streams ;
2014-01-16 01:53:03 +01:00
if ( ff_check_interrupt ( & ic -> interrupt_callback )) {
ret = AVERROR_EXIT ;
2009-06-18 00:22:08 +00:00
av_log ( ic , AV_LOG_DEBUG , "interrupted \n " );
2009-02-23 02:38:45 +00:00
break ;
}
2002-05-20 16:28:47 +00:00
/* check if one codec still needs to be handled */
2014-01-16 01:53:03 +01:00
for ( i = 0 ; i < ic -> nb_streams ; i ++ ) {
2011-02-28 02:20:56 +02:00
int fps_analyze_framecount = 20 ;
2017-10-31 20:44:21 +01:00
int count ;
2011-02-28 02:20:56 +02:00
2002-05-20 16:28:47 +00:00
st = ic -> streams [ i ];
2012-07-16 00:27:09 +02:00
if ( ! has_codec_parameters ( st , NULL ))
2002-05-20 16:28:47 +00:00
break ;
2014-01-16 01:53:03 +01:00
/* If the timebase is coarse (like the usual millisecond precision
* of mkv), we need to analyze more frames to reliably arrive at
* the correct fps. */
2011-02-28 02:20:56 +02:00
if ( av_q2d ( st -> time_base ) > 0.0005 )
fps_analyze_framecount *= 2 ;
2016-04-10 20:58:15 +01:00
if ( ! tb_unreliable ( st -> internal -> avctx ))
2014-04-28 16:28:41 +02:00
fps_analyze_framecount = 0 ;
2011-05-09 14:34:23 -07:00
if ( ic -> fps_probe_size >= 0 )
fps_analyze_framecount = ic -> fps_probe_size ;
2013-02-15 02:17:39 +01:00
if ( st -> disposition & AV_DISPOSITION_ATTACHED_PIC )
fps_analyze_framecount = 0 ;
2004-12-21 02:16:11 +00:00
/* variable fps and no guess at the real fps */
2017-10-31 20:44:21 +01:00
count = ( ic -> iformat -> flags & AVFMT_NOTIMESTAMPS ) ?
2020-10-09 08:15:27 +02:00
st -> internal -> info -> codec_info_duration_fields / 2 :
st -> internal -> info -> duration_count ;
2014-04-28 16:28:41 +02:00
if ( ! ( st -> r_frame_rate . num && st -> avg_frame_rate . num ) &&
2016-04-10 20:58:15 +01:00
st -> codecpar -> codec_type == AVMEDIA_TYPE_VIDEO ) {
2015-04-18 00:58:51 +02:00
if ( count < fps_analyze_framecount )
break ;
}
2017-10-31 20:44:21 +01:00
// Look at the first 3 frames if there is evidence of frame delay
// but the decoder delay is not set.
2020-10-09 08:15:27 +02:00
if ( st -> internal -> info -> frame_delay_evidence && count < 2 && st -> internal -> avctx -> has_b_frames == 0 )
2017-10-31 20:44:21 +01:00
break ;
2017-03-24 18:42:19 -03:00
if ( ! st -> internal -> avctx -> extradata &&
( ! st -> internal -> extract_extradata . inited ||
st -> internal -> extract_extradata . bsf ) &&
extract_extradata_check ( st ))
2005-06-27 00:04:03 +00:00
break ;
2021-06-05 11:12:03 -03:00
if ( st -> internal -> first_dts == AV_NOPTS_VALUE &&
2014-06-10 14:22:13 +02:00
! ( ic -> iformat -> flags & AVFMT_NOTIMESTAMPS ) &&
2021-05-01 23:35:45 -03:00
st -> internal -> codec_info_nb_frames < (( st -> disposition & AV_DISPOSITION_ATTACHED_PIC ) ? 1 : ic -> max_ts_probe ) &&
2014-06-18 20:42:52 +02:00
( st -> codecpar -> codec_type == AVMEDIA_TYPE_VIDEO ||
st -> codecpar -> codec_type == AVMEDIA_TYPE_AUDIO ))
2007-08-04 22:46:13 +00:00
break ;
2002-05-20 16:28:47 +00:00
}
2014-12-01 15:26:58 +01:00
analyzed_all_streams = 0 ;
2016-10-28 12:18:35 +02:00
if ( ! missing_streams || !* missing_streams )
2019-12-02 09:53:47 +08:00
if ( i == ic -> nb_streams ) {
analyzed_all_streams = 1 ;
/* NOTE: If the format has no header, then we need to read some
* packets to get most of the streams, so we cannot stop here. */
if ( ! ( ic -> ctx_flags & AVFMTCTX_NOHEADER )) {
/* If we found the info for all the codecs, we can stop. */
ret = count ;
av_log ( ic , AV_LOG_DEBUG , "All info found \n " );
flush_codecs = 0 ;
break ;
}
2002-05-20 16:28:47 +00:00
}
2014-01-16 01:53:03 +01:00
/* We did not get all the codec info, but we read too much data. */
2014-07-30 11:09:25 +02:00
if ( read_size >= probesize ) {
2006-09-26 17:27:08 +00:00
ret = count ;
2014-01-16 01:53:03 +01:00
av_log ( ic , AV_LOG_DEBUG ,
2014-07-30 11:09:25 +02:00
"Probe buffer size limit of %" PRId64 " bytes reached \n " , probesize );
2012-04-21 12:05:23 +02:00
for ( i = 0 ; i < ic -> nb_streams ; i ++ )
if ( ! ic -> streams [ i ] -> r_frame_rate . num &&
2020-10-09 08:15:27 +02:00
ic -> streams [ i ] -> internal -> info -> duration_count <= 1 &&
2016-04-10 20:58:15 +01:00
ic -> streams [ i ] -> codecpar -> codec_type == AVMEDIA_TYPE_VIDEO &&
2013-09-17 00:08:12 +02:00
strcmp ( ic -> iformat -> name , "image2" ))
2012-04-21 12:05:23 +02:00
av_log ( ic , AV_LOG_WARNING ,
"Stream #%d: not enough frames to estimate rate; "
"consider increasing probesize \n " , i );
2006-09-26 17:27:08 +00:00
break ;
}
2002-05-20 16:28:47 +00:00
2014-01-16 01:53:03 +01:00
/* NOTE: A new stream can be added there if no header in file
* (AVFMTCTX_NOHEADER). */
2021-01-31 13:05:49 -03:00
ret = read_frame_internal ( ic , pkt1 );
2011-06-29 13:50:21 -07:00
if ( ret == AVERROR ( EAGAIN ))
continue ;
if ( ret < 0 ) {
2012-01-02 09:01:02 +01:00
/* EOF or error*/
2016-03-12 02:40:25 -08:00
eof_reached = 1 ;
2003-11-10 18:37:55 +00:00
break ;
}
2015-10-23 11:11:32 +02:00
if ( ! ( ic -> flags & AVFMT_FLAG_NOBUFFER )) {
2020-08-17 12:03:50 -03:00
ret = avpriv_packet_list_put ( & ic -> internal -> packet_buffer ,
2018-03-27 19:48:18 -03:00
& ic -> internal -> packet_buffer_end ,
2021-01-31 13:05:49 -03:00
pkt1 , NULL , 0 );
2015-10-23 11:11:32 +02:00
if ( ret < 0 )
2019-09-20 22:39:12 +02:00
goto unref_then_goto_end ;
2019-09-20 22:39:10 +02:00
pkt = & ic -> internal -> packet_buffer_end -> pkt ;
} else {
2021-01-31 13:05:49 -03:00
pkt = pkt1 ;
2012-07-26 16:35:12 -07:00
}
2003-11-10 18:37:55 +00:00
2002-05-20 16:28:47 +00:00
st = ic -> streams [ pkt -> stream_index ];
2013-11-18 03:02:36 +01:00
if ( ! ( st -> disposition & AV_DISPOSITION_ATTACHED_PIC ))
read_size += pkt -> size ;
2014-06-18 20:42:52 +02:00
avctx = st -> internal -> avctx ;
if ( ! st -> internal -> avctx_inited ) {
ret = avcodec_parameters_to_context ( avctx , st -> codecpar );
if ( ret < 0 )
2019-09-20 22:39:12 +02:00
goto unref_then_goto_end ;
2014-06-18 20:42:52 +02:00
st -> internal -> avctx_inited = 1 ;
}
2021-05-01 23:35:45 -03:00
if ( pkt -> dts != AV_NOPTS_VALUE && st -> internal -> codec_info_nb_frames > 1 ) {
2012-06-28 15:49:51 +02:00
/* check for non-increasing dts */
2020-10-09 08:15:27 +02:00
if ( st -> internal -> info -> fps_last_dts != AV_NOPTS_VALUE &&
st -> internal -> info -> fps_last_dts >= pkt -> dts ) {
2014-01-26 23:35:38 +01:00
av_log ( ic , AV_LOG_DEBUG ,
2014-01-16 01:53:03 +01:00
"Non-increasing DTS in stream %d: packet %d with DTS "
"%" PRId64 ", packet %d with DTS %" PRId64 " \n " ,
2020-10-09 08:15:27 +02:00
st -> index , st -> internal -> info -> fps_last_dts_idx ,
2021-05-01 23:35:45 -03:00
st -> internal -> info -> fps_last_dts , st -> internal -> codec_info_nb_frames ,
2014-01-16 01:53:03 +01:00
pkt -> dts );
2020-10-09 08:15:27 +02:00
st -> internal -> info -> fps_first_dts =
st -> internal -> info -> fps_last_dts = AV_NOPTS_VALUE ;
2012-06-28 15:49:51 +02:00
}
2014-01-16 01:53:03 +01:00
/* Check for a discontinuity in dts. If the difference in dts
* is more than 1000 times the average packet duration in the
* sequence, we treat it as a discontinuity. */
2020-10-09 08:15:27 +02:00
if ( st -> internal -> info -> fps_last_dts != AV_NOPTS_VALUE &&
st -> internal -> info -> fps_last_dts_idx > st -> internal -> info -> fps_first_dts_idx &&
( pkt -> dts - ( uint64_t ) st -> internal -> info -> fps_last_dts ) / 1000 >
( st -> internal -> info -> fps_last_dts - ( uint64_t ) st -> internal -> info -> fps_first_dts ) /
( st -> internal -> info -> fps_last_dts_idx - st -> internal -> info -> fps_first_dts_idx )) {
2014-01-16 01:53:03 +01:00
av_log ( ic , AV_LOG_WARNING ,
"DTS discontinuity in stream %d: packet %d with DTS "
"%" PRId64 ", packet %d with DTS %" PRId64 " \n " ,
2020-10-09 08:15:27 +02:00
st -> index , st -> internal -> info -> fps_last_dts_idx ,
2021-05-01 23:35:45 -03:00
st -> internal -> info -> fps_last_dts , st -> internal -> codec_info_nb_frames ,
2014-01-16 01:53:03 +01:00
pkt -> dts );
2020-10-09 08:15:27 +02:00
st -> internal -> info -> fps_first_dts =
st -> internal -> info -> fps_last_dts = AV_NOPTS_VALUE ;
2012-08-11 21:24:40 +03:00
}
2012-06-28 15:49:51 +02:00
/* update stored dts values */
2020-10-09 08:15:27 +02:00
if ( st -> internal -> info -> fps_first_dts == AV_NOPTS_VALUE ) {
st -> internal -> info -> fps_first_dts = pkt -> dts ;
2021-05-01 23:35:45 -03:00
st -> internal -> info -> fps_first_dts_idx = st -> internal -> codec_info_nb_frames ;
2012-06-28 15:49:51 +02:00
}
2020-10-09 08:15:27 +02:00
st -> internal -> info -> fps_last_dts = pkt -> dts ;
2021-05-01 23:35:45 -03:00
st -> internal -> info -> fps_last_dts_idx = st -> internal -> codec_info_nb_frames ;
2012-07-29 22:58:17 +02:00
}
2021-05-01 23:35:45 -03:00
if ( st -> internal -> codec_info_nb_frames > 1 ) {
2014-01-26 23:35:38 +01:00
int64_t t = 0 ;
2015-07-16 03:37:43 +02:00
int64_t limit ;
2014-05-26 21:54:27 +02:00
2012-01-05 00:49:02 +01:00
if ( st -> time_base . den > 0 )
2020-10-09 08:15:27 +02:00
t = av_rescale_q ( st -> internal -> info -> codec_info_duration , st -> time_base , AV_TIME_BASE_Q );
2012-01-05 00:49:02 +01:00
if ( st -> avg_frame_rate . num > 0 )
2021-05-01 23:35:45 -03:00
t = FFMAX ( t , av_rescale_q ( st -> internal -> codec_info_nb_frames , av_inv_q ( st -> avg_frame_rate ), AV_TIME_BASE_Q ));
2012-01-05 00:49:02 +01:00
2014-01-26 23:35:38 +01:00
if ( t == 0
2021-05-01 23:35:45 -03:00
&& st -> internal -> codec_info_nb_frames > 30
2020-10-09 08:15:27 +02:00
&& st -> internal -> info -> fps_first_dts != AV_NOPTS_VALUE
2020-11-10 22:27:47 +01:00
&& st -> internal -> info -> fps_last_dts != AV_NOPTS_VALUE ) {
int64_t dur = av_sat_sub64 ( st -> internal -> info -> fps_last_dts , st -> internal -> info -> fps_first_dts );
t = FFMAX ( t , av_rescale_q ( dur , st -> time_base , AV_TIME_BASE_Q ));
}
2013-07-07 15:03:12 +02:00
2015-07-16 03:37:43 +02:00
if ( analyzed_all_streams ) limit = max_analyze_duration ;
2016-04-10 20:58:15 +01:00
else if ( avctx -> codec_type == AVMEDIA_TYPE_SUBTITLE ) limit = max_subtitle_analyze_duration ;
2015-07-16 03:37:43 +02:00
else limit = max_stream_analyze_duration ;
if ( t >= limit ) {
2015-07-16 03:30:24 +02:00
av_log ( ic , AV_LOG_VERBOSE , "max_analyze_duration %" PRId64 " reached at %" PRId64 " microseconds st:%d \n " ,
2015-09-11 12:17:59 -07:00
limit ,
2015-07-16 03:30:24 +02:00
t , pkt -> stream_index );
2013-09-16 15:51:46 -04:00
if ( ic -> flags & AVFMT_FLAG_NOBUFFER )
2021-01-31 13:05:49 -03:00
av_packet_unref ( pkt1 );
2009-03-19 21:54:34 +00:00
break ;
2009-06-18 00:22:08 +00:00
}
2012-10-14 18:53:05 +02:00
if ( pkt -> duration ) {
2021-06-09 21:10:32 +02:00
if ( avctx -> codec_type == AVMEDIA_TYPE_SUBTITLE && pkt -> pts != AV_NOPTS_VALUE && st -> start_time != AV_NOPTS_VALUE && pkt -> pts >= st -> start_time
&& ( uint64_t ) pkt -> pts - st -> start_time < INT64_MAX
) {
2020-10-09 08:15:27 +02:00
st -> internal -> info -> codec_info_duration = FFMIN ( pkt -> pts - st -> start_time , st -> internal -> info -> codec_info_duration + pkt -> duration );
2015-10-02 22:39:24 -05:00
} else
2020-10-09 08:15:27 +02:00
st -> internal -> info -> codec_info_duration += pkt -> duration ;
2021-05-01 23:28:18 -03:00
st -> internal -> info -> codec_info_duration_fields += st -> internal -> parser && st -> internal -> need_parsing && avctx -> ticks_per_frame == 2
? st -> internal -> parser -> repeat_pict + 1 : 2 ;
2012-10-14 18:53:05 +02:00
}
2009-03-19 21:54:34 +00:00
}
2017-10-31 20:44:21 +01:00
if ( st -> codecpar -> codec_type == AVMEDIA_TYPE_VIDEO ) {
2012-06-26 13:10:01 +02:00
#if FF_API_R_FRAME_RATE
2014-06-02 17:09:53 +02:00
ff_rfps_add_frame ( ic , st , pkt -> dts );
2012-06-26 13:10:01 +02:00
#endif
2017-10-31 20:44:21 +01:00
if ( pkt -> dts != pkt -> pts && pkt -> dts != AV_NOPTS_VALUE && pkt -> pts != AV_NOPTS_VALUE )
2020-10-09 08:15:27 +02:00
st -> internal -> info -> frame_delay_evidence = 1 ;
2017-10-31 20:44:21 +01:00
}
2017-03-24 18:42:19 -03:00
if ( ! st -> internal -> avctx -> extradata ) {
2021-03-18 05:23:54 +01:00
ret = extract_extradata ( ic , st , pkt );
2017-03-24 18:42:19 -03:00
if ( ret < 0 )
2019-09-20 22:39:12 +02:00
goto unref_then_goto_end ;
2005-06-27 00:04:03 +00:00
}
2005-12-17 18:14:38 +00:00
2014-01-16 01:53:03 +01:00
/* If still no information, we try to open the codec and to
* decompress the frame. We try to avoid that in most cases as
* it takes longer and uses more memory. For MPEG-4, we need to
* decompress for QuickTime.
*
2015-07-07 01:41:27 +01:00
* If AV_CODEC_CAP_CHANNEL_CONF is set this will force decoding of at
2014-01-16 01:53:03 +01:00
* least one frame of codec data, this makes sure the codec initializes
* the channel configuration and does not only trust the values from
* the container. */
2014-01-26 23:35:38 +01:00
try_decode_frame ( ic , st , pkt ,
2014-01-16 01:53:03 +01:00
( options && i < orig_nb_streams ) ? & options [ i ] : NULL );
2005-12-17 18:14:38 +00:00
2013-09-16 15:51:46 -04:00
if ( ic -> flags & AVFMT_FLAG_NOBUFFER )
2021-01-31 13:05:49 -03:00
av_packet_unref ( pkt1 );
2013-09-16 15:51:46 -04:00
2021-05-01 23:35:45 -03:00
st -> internal -> codec_info_nb_frames ++ ;
2002-05-20 16:28:47 +00:00
count ++ ;
}
2016-06-09 19:11:18 +02:00
if ( eof_reached ) {
2016-03-12 02:40:25 -08:00
int stream_index ;
for ( stream_index = 0 ; stream_index < ic -> nb_streams ; stream_index ++ ) {
2016-06-09 19:09:36 +02:00
st = ic -> streams [ stream_index ];
2016-06-09 19:11:18 +02:00
avctx = st -> internal -> avctx ;
if ( ! has_codec_parameters ( st , NULL )) {
2016-09-21 19:00:46 +02:00
const AVCodec * codec = find_probe_decoder ( ic , st , st -> codecpar -> codec_id );
2016-06-09 19:11:18 +02:00
if ( codec && ! avctx -> codec ) {
2016-11-25 21:56:03 +01:00
AVDictionary * opts = NULL ;
if ( ic -> codec_whitelist )
av_dict_set ( & opts , "codec_whitelist" , ic -> codec_whitelist , 0 );
if ( avcodec_open2 ( avctx , codec , ( options && stream_index < orig_nb_streams ) ? & options [ stream_index ] : & opts ) < 0 )
2016-06-09 19:11:18 +02:00
av_log ( ic , AV_LOG_WARNING ,
2016-12-05 15:17:13 +08:00
"Failed to open codec in %s \n " , __FUNCTION__ );
2016-11-25 21:56:03 +01:00
av_dict_free ( & opts );
2016-06-09 19:11:18 +02:00
}
}
2016-06-09 19:09:36 +02:00
2016-03-12 02:40:25 -08:00
// EOF already reached while reading the stream above.
// So continue with reoordering DTS with whatever delay we have.
2016-06-09 19:11:18 +02:00
if ( ic -> internal -> packet_buffer && ! has_decode_delay_been_guessed ( st )) {
2016-03-12 02:40:25 -08:00
update_dts_from_pts ( ic , stream_index , ic -> internal -> packet_buffer );
}
}
}
2012-01-06 11:51:12 +01:00
if ( flush_codecs ) {
2021-01-31 13:05:49 -03:00
AVPacket * empty_pkt = ic -> internal -> pkt ;
2012-03-06 03:56:25 +01:00
int err = 0 ;
2021-01-31 13:05:49 -03:00
av_packet_unref ( empty_pkt );
2012-01-06 11:51:12 +01:00
2014-01-26 23:35:38 +01:00
for ( i = 0 ; i < ic -> nb_streams ; i ++ ) {
2012-07-16 00:27:09 +02:00
2012-01-06 11:51:12 +01:00
st = ic -> streams [ i ];
/* flush the decoders */
2020-10-09 08:15:27 +02:00
if ( st -> internal -> info -> found_decoder == 1 ) {
2012-03-06 03:56:25 +01:00
do {
2021-01-31 13:05:49 -03:00
err = try_decode_frame ( ic , st , empty_pkt ,
2014-01-26 23:35:38 +01:00
( options && i < orig_nb_streams )
? & options [ i ] : NULL );
2012-07-16 00:27:09 +02:00
} while ( err > 0 && ! has_codec_parameters ( st , NULL ));
2012-01-06 11:51:12 +01:00
2012-03-06 03:56:25 +01:00
if ( err < 0 ) {
av_log ( ic , AV_LOG_INFO ,
"decoding for stream %d failed \n " , st -> index );
}
2012-01-27 01:42:53 +01:00
}
2012-01-06 11:51:12 +01:00
}
}
2013-12-05 16:56:17 +01:00
ff_rfps_calculate ( ic );
2014-01-16 01:53:03 +01:00
for ( i = 0 ; i < ic -> nb_streams ; i ++ ) {
2002-05-20 16:28:47 +00:00
st = ic -> streams [ i ];
2014-06-18 20:42:52 +02:00
avctx = st -> internal -> avctx ;
if ( avctx -> codec_type == AVMEDIA_TYPE_VIDEO ) {
2016-04-10 20:58:15 +01:00
if ( avctx -> codec_id == AV_CODEC_ID_RAWVIDEO && ! avctx -> codec_tag && ! avctx -> bits_per_coded_sample ) {
uint32_t tag = avcodec_pix_fmt_to_codec_tag ( avctx -> pix_fmt );
if ( avpriv_find_pix_fmt ( avpriv_get_raw_pix_fmt_tags (), tag ) == avctx -> pix_fmt )
avctx -> codec_tag = tag ;
2011-03-09 15:12:24 +01:00
}
2004-12-19 01:23:22 +00:00
2012-07-29 22:58:17 +02:00
/* estimate average framerate if not set by demuxer */
2020-10-09 08:15:27 +02:00
if ( st -> internal -> info -> codec_info_duration_fields &&
2014-01-26 23:35:38 +01:00
! st -> avg_frame_rate . num &&
2020-10-09 08:15:27 +02:00
st -> internal -> info -> codec_info_duration ) {
2014-01-16 01:53:03 +01:00
int best_fps = 0 ;
2012-07-27 14:04:07 +02:00
double best_error = 0.01 ;
2017-05-23 13:36:38 +02:00
AVRational codec_frame_rate = avctx -> framerate ;
2012-06-28 15:49:51 +02:00
2020-10-09 08:15:27 +02:00
if ( st -> internal -> info -> codec_info_duration >= INT64_MAX / st -> time_base . num / 2 ||
st -> internal -> info -> codec_info_duration_fields >= INT64_MAX / st -> time_base . den ||
st -> internal -> info -> codec_info_duration < 0 )
2013-07-15 16:44:20 +03:00
continue ;
2012-03-13 21:45:05 +01:00
av_reduce ( & st -> avg_frame_rate . num , & st -> avg_frame_rate . den ,
2020-10-09 08:15:27 +02:00
st -> internal -> info -> codec_info_duration_fields * ( int64_t ) st -> time_base . den ,
st -> internal -> info -> codec_info_duration * 2 * ( int64_t ) st -> time_base . num , 60000 );
2012-07-27 14:04:07 +02:00
2014-01-16 01:53:03 +01:00
/* Round guessed framerate to a "standard" framerate if it's
* within 1% of the original estimate. */
2014-01-29 15:12:48 +01:00
for ( j = 0 ; j < MAX_STD_TIMEBASES ; j ++ ) {
2014-01-16 01:53:03 +01:00
AVRational std_fps = { get_std_framerate ( j ), 12 * 1001 };
double error = fabs ( av_q2d ( st -> avg_frame_rate ) /
av_q2d ( std_fps ) - 1 );
2012-07-27 14:04:07 +02:00
if ( error < best_error ) {
best_error = error ;
best_fps = std_fps . num ;
}
2017-05-23 13:36:38 +02:00
if ( ic -> internal -> prefer_codec_framerate && codec_frame_rate . num > 0 && codec_frame_rate . den > 0 ) {
error = fabs ( av_q2d ( codec_frame_rate ) /
av_q2d ( std_fps ) - 1 );
if ( error < best_error ) {
best_error = error ;
best_fps = std_fps . num ;
}
}
2012-07-27 14:04:07 +02:00
}
2014-01-16 01:53:03 +01:00
if ( best_fps )
2012-07-27 14:04:07 +02:00
av_reduce ( & st -> avg_frame_rate . num , & st -> avg_frame_rate . den ,
2014-01-16 01:53:03 +01:00
best_fps , 12 * 1001 , INT_MAX );
2012-06-28 15:49:51 +02:00
}
2004-12-19 01:23:22 +00:00
2014-01-26 23:35:38 +01:00
if ( ! st -> r_frame_rate . num ) {
2016-04-10 20:58:15 +01:00
if ( avctx -> time_base . den * ( int64_t ) st -> time_base . num
2021-04-12 22:33:06 +02:00
<= avctx -> time_base . num * ( uint64_t ) avctx -> ticks_per_frame * st -> time_base . den ) {
2017-08-17 00:20:01 +02:00
av_reduce ( & st -> r_frame_rate . num , & st -> r_frame_rate . den ,
avctx -> time_base . den , ( int64_t ) avctx -> time_base . num * avctx -> ticks_per_frame , INT_MAX );
2014-01-26 23:35:38 +01:00
} else {
2006-10-03 19:13:27 +00:00
st -> r_frame_rate . num = st -> time_base . den ;
st -> r_frame_rate . den = st -> time_base . num ;
}
2003-03-12 15:16:19 +00:00
}
2020-10-09 09:22:36 +02:00
if ( st -> internal -> display_aspect_ratio . num && st -> internal -> display_aspect_ratio . den ) {
2016-04-10 20:58:15 +01:00
AVRational hw_ratio = { avctx -> height , avctx -> width };
2020-10-09 09:22:36 +02:00
st -> sample_aspect_ratio = av_mul_q ( st -> internal -> display_aspect_ratio ,
2014-11-17 17:54:32 +01:00
hw_ratio );
}
2014-06-18 20:42:52 +02:00
} else if ( avctx -> codec_type == AVMEDIA_TYPE_AUDIO ) {
if ( ! avctx -> bits_per_coded_sample )
avctx -> bits_per_coded_sample =
av_get_bits_per_sample ( avctx -> codec_id );
2011-03-24 12:09:02 -04:00
// set stream disposition based on audio service type
2014-06-18 20:42:52 +02:00
switch ( avctx -> audio_service_type ) {
2011-03-24 12:09:02 -04:00
case AV_AUDIO_SERVICE_TYPE_EFFECTS :
2014-01-16 01:53:03 +01:00
st -> disposition = AV_DISPOSITION_CLEAN_EFFECTS ;
break ;
2011-03-24 12:09:02 -04:00
case AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED :
2014-01-16 01:53:03 +01:00
st -> disposition = AV_DISPOSITION_VISUAL_IMPAIRED ;
break ;
2011-03-24 12:09:02 -04:00
case AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED :
2014-01-16 01:53:03 +01:00
st -> disposition = AV_DISPOSITION_HEARING_IMPAIRED ;
break ;
2011-03-24 12:09:02 -04:00
case AV_AUDIO_SERVICE_TYPE_COMMENTARY :
2014-01-16 01:53:03 +01:00
st -> disposition = AV_DISPOSITION_COMMENT ;
break ;
2011-03-24 12:09:02 -04:00
case AV_AUDIO_SERVICE_TYPE_KARAOKE :
2014-01-16 01:53:03 +01:00
st -> disposition = AV_DISPOSITION_KARAOKE ;
break ;
2011-03-24 12:09:02 -04:00
}
2002-05-20 16:28:47 +00:00
}
}
2016-04-13 17:10:44 +01:00
if ( probesize )
estimate_timings ( ic , old_offset );
2014-11-03 22:53:48 +01:00
av_opt_set ( ic , "skip_clear" , "0" , AV_OPT_SEARCH_CHILDREN );
2013-07-02 15:06:43 +02:00
if ( ret >= 0 && ic -> nb_streams )
2014-01-26 23:35:38 +01:00
/* We could not have all the codec parameters before EOF. */
ret = - 1 ;
for ( i = 0 ; i < ic -> nb_streams ; i ++ ) {
2013-06-20 09:34:15 +02:00
const char * errmsg ;
st = ic -> streams [ i ];
2016-04-10 20:58:15 +01:00
/* if no packet was ever seen, update context now for has_codec_parameters */
if ( ! st -> internal -> avctx_inited ) {
2016-06-09 11:22:01 +02:00
if ( st -> codecpar -> codec_type == AVMEDIA_TYPE_AUDIO &&
st -> codecpar -> format == AV_SAMPLE_FMT_NONE )
st -> codecpar -> format = st -> internal -> avctx -> sample_fmt ;
2016-04-10 20:58:15 +01:00
ret = avcodec_parameters_to_context ( st -> internal -> avctx , st -> codecpar );
if ( ret < 0 )
goto find_stream_info_err ;
}
2013-06-20 09:34:15 +02:00
if ( ! has_codec_parameters ( st , & errmsg )) {
char buf [ 256 ];
2016-04-10 20:58:15 +01:00
avcodec_string ( buf , sizeof ( buf ), st -> internal -> avctx , 0 );
2013-06-20 09:34:15 +02:00
av_log ( ic , AV_LOG_WARNING ,
"Could not find codec parameters for stream %d (%s): %s \n "
2020-06-08 11:07:27 +02:00
"Consider increasing the value for the 'analyzeduration' (%" PRId64 ") and 'probesize' (%" PRId64 ") options \n " ,
i , buf , errmsg , ic -> max_analyze_duration , ic -> probesize );
2013-06-20 09:34:15 +02:00
} else {
ret = 0 ;
}
}
2020-11-21 14:51:25 +01:00
ret = compute_chapters_end ( ic );
if ( ret < 0 )
goto find_stream_info_err ;
2008-05-24 21:44:29 +00:00
2014-06-18 20:42:52 +02:00
/* update the stream parameters from the internal codec contexts */
for ( i = 0 ; i < ic -> nb_streams ; i ++ ) {
st = ic -> streams [ i ];
2016-04-10 20:58:15 +01:00
if ( st -> internal -> avctx_inited ) {
ret = avcodec_parameters_from_context ( st -> codecpar , st -> internal -> avctx );
if ( ret < 0 )
goto find_stream_info_err ;
2020-03-05 09:17:22 +01:00
ret = add_coded_side_data ( st , st -> internal -> avctx );
if ( ret < 0 )
goto find_stream_info_err ;
2016-04-10 20:58:15 +01:00
}
2014-06-18 20:42:52 +02:00
st -> internal -> avctx_inited = 0 ;
}
2014-01-16 01:53:03 +01:00
find_stream_info_err :
for ( i = 0 ; i < ic -> nb_streams ; i ++ ) {
2013-02-23 22:25:49 +01:00
st = ic -> streams [ i ];
2020-10-09 08:15:27 +02:00
if ( st -> internal -> info )
av_freep ( & st -> internal -> info -> duration_error );
2017-04-12 01:46:30 +02:00
avcodec_close ( ic -> streams [ i ] -> internal -> avctx );
2020-10-09 08:15:27 +02:00
av_freep ( & ic -> streams [ i ] -> internal -> info );
2017-03-24 18:42:19 -03:00
av_bsf_free ( & ic -> streams [ i ] -> internal -> extract_extradata . bsf );
2011-12-25 11:45:05 +01:00
}
2021-08-04 16:52:07 +02:00
if ( ic -> pb ) {
FFIOContext * const ctx = ffiocontext ( ic -> pb );
2013-12-05 16:06:24 +01:00
av_log ( ic , AV_LOG_DEBUG , "After avformat_find_stream_info() pos: %" PRId64 " bytes read:%" PRId64 " seeks:%d frames:%d \n " ,
2021-08-04 16:52:07 +02:00
avio_tell ( ic -> pb ), ctx -> bytes_read , ctx -> seek_count , count );
}
2002-05-20 16:28:47 +00:00
return ret ;
2019-09-20 22:39:12 +02:00
unref_then_goto_end :
2021-01-31 13:05:49 -03:00
av_packet_unref ( pkt1 );
2019-09-20 22:39:12 +02:00
goto find_stream_info_err ;
2002-05-20 16:28:47 +00:00
}
2011-08-22 23:42:19 +02:00
AVProgram * av_find_program_from_stream ( AVFormatContext * ic , AVProgram * last , int s )
2010-12-27 09:08:20 +00:00
{
int i , j ;
2011-08-22 23:42:19 +02:00
for ( i = 0 ; i < ic -> nb_programs ; i ++ ) {
if ( ic -> programs [ i ] == last ) {
last = NULL ;
} else {
if ( ! last )
for ( j = 0 ; j < ic -> programs [ i ] -> nb_stream_indexes ; j ++ )
if ( ic -> programs [ i ] -> stream_index [ j ] == s )
return ic -> programs [ i ];
}
}
2010-12-27 09:08:20 +00:00
return NULL ;
}
2014-01-16 01:53:03 +01:00
int av_find_best_stream ( AVFormatContext * ic , enum AVMediaType type ,
int wanted_stream_nb , int related_stream ,
2021-02-25 01:53:40 +01:00
const AVCodec ** decoder_ret , int flags )
2010-12-27 09:08:20 +00:00
{
2011-02-20 01:18:30 +01:00
int i , nb_streams = ic -> nb_streams ;
2017-06-02 21:52:13 +02:00
int ret = AVERROR_STREAM_NOT_FOUND ;
2017-06-02 22:45:02 +02:00
int best_count = - 1 , best_multiframe = - 1 , best_disposition = - 1 ;
int count , multiframe , disposition ;
int64_t best_bitrate = - 1 ;
int64_t bitrate ;
2010-12-27 09:08:20 +00:00
unsigned * program = NULL ;
2014-05-07 05:52:58 +02:00
const AVCodec * decoder = NULL , * best_decoder = NULL ;
2010-12-27 09:08:20 +00:00
if ( related_stream >= 0 && wanted_stream_nb < 0 ) {
2011-08-22 23:42:19 +02:00
AVProgram * p = av_find_program_from_stream ( ic , NULL , related_stream );
2010-12-27 09:08:20 +00:00
if ( p ) {
2014-01-16 01:53:03 +01:00
program = p -> stream_index ;
2010-12-27 09:08:20 +00:00
nb_streams = p -> nb_stream_indexes ;
}
}
for ( i = 0 ; i < nb_streams ; i ++ ) {
2011-02-20 01:18:30 +01:00
int real_stream_index = program ? program [ i ] : i ;
2014-01-16 01:53:03 +01:00
AVStream * st = ic -> streams [ real_stream_index ];
2014-06-18 20:42:52 +02:00
AVCodecParameters * par = st -> codecpar ;
if ( par -> codec_type != type )
2010-12-27 09:08:20 +00:00
continue ;
2011-02-20 01:18:30 +01:00
if ( wanted_stream_nb >= 0 && real_stream_index != wanted_stream_nb )
2010-12-27 09:08:20 +00:00
continue ;
2016-04-10 20:58:15 +01:00
if ( type == AVMEDIA_TYPE_AUDIO && ! ( par -> channels && par -> sample_rate ))
2014-01-16 00:36:27 +01:00
continue ;
2010-12-27 09:08:20 +00:00
if ( decoder_ret ) {
2016-04-10 20:58:15 +01:00
decoder = find_decoder ( ic , st , par -> codec_id );
2010-12-27 09:08:20 +00:00
if ( ! decoder ) {
if ( ret < 0 )
ret = AVERROR_DECODER_NOT_FOUND ;
continue ;
}
}
2019-06-20 12:26:27 +08:00
disposition = ! ( st -> disposition & ( AV_DISPOSITION_HEARING_IMPAIRED | AV_DISPOSITION_VISUAL_IMPAIRED ))
+ !! ( st -> disposition & AV_DISPOSITION_DEFAULT );
2021-05-01 23:35:45 -03:00
count = st -> internal -> codec_info_nb_frames ;
2016-04-10 20:58:15 +01:00
bitrate = par -> bit_rate ;
2012-11-18 13:19:14 +01:00
multiframe = FFMIN ( 5 , count );
2017-06-02 21:52:13 +02:00
if (( best_disposition > disposition ) ||
( best_disposition == disposition && best_multiframe > multiframe ) ||
( best_disposition == disposition && best_multiframe == multiframe && best_bitrate > bitrate ) ||
( best_disposition == disposition && best_multiframe == multiframe && best_bitrate == bitrate && best_count >= count ))
2010-12-27 09:08:20 +00:00
continue ;
2017-06-02 21:52:13 +02:00
best_disposition = disposition ;
2014-01-26 23:35:38 +01:00
best_count = count ;
2012-11-18 13:19:14 +01:00
best_bitrate = bitrate ;
best_multiframe = multiframe ;
2014-01-16 01:53:03 +01:00
ret = real_stream_index ;
2010-12-27 09:08:20 +00:00
best_decoder = decoder ;
if ( program && i == nb_streams - 1 && ret < 0 ) {
2014-01-16 01:53:03 +01:00
program = NULL ;
2010-12-27 09:08:20 +00:00
nb_streams = ic -> nb_streams ;
2014-01-16 01:53:03 +01:00
/* no related stream found, try again with everything */
i = 0 ;
2010-12-27 09:08:20 +00:00
}
}
if ( decoder_ret )
2021-02-25 01:53:40 +01:00
* decoder_ret = best_decoder ;
2010-12-27 09:08:20 +00:00
return ret ;
}
2003-11-10 18:37:55 +00:00
/*******************************************************/
int av_read_play ( AVFormatContext * s )
{
2007-12-17 09:28:46 +00:00
if ( s -> iformat -> read_play )
return s -> iformat -> read_play ( s );
2007-12-20 00:25:18 +00:00
if ( s -> pb )
2011-04-12 09:37:10 +02:00
return avio_pause ( s -> pb , 0 );
2007-12-17 09:28:46 +00:00
return AVERROR ( ENOSYS );
2003-11-10 18:37:55 +00:00
}
int av_read_pause ( AVFormatContext * s )
{
2007-12-17 09:28:46 +00:00
if ( s -> iformat -> read_pause )
return s -> iformat -> read_pause ( s );
2007-12-20 00:25:18 +00:00
if ( s -> pb )
2011-04-12 09:37:10 +02:00
return avio_pause ( s -> pb , 1 );
2007-12-17 09:28:46 +00:00
return AVERROR ( ENOSYS );
2003-11-10 18:37:55 +00:00
}
2016-07-13 17:00:11 +02:00
int ff_stream_encode_params_copy ( AVStream * dst , const AVStream * src )
{
int ret , i ;
dst -> id = src -> id ;
dst -> time_base = src -> time_base ;
dst -> nb_frames = src -> nb_frames ;
dst -> disposition = src -> disposition ;
dst -> sample_aspect_ratio = src -> sample_aspect_ratio ;
dst -> avg_frame_rate = src -> avg_frame_rate ;
dst -> r_frame_rate = src -> r_frame_rate ;
av_dict_free ( & dst -> metadata );
ret = av_dict_copy ( & dst -> metadata , src -> metadata , 0 );
if ( ret < 0 )
return ret ;
ret = avcodec_parameters_copy ( dst -> codecpar , src -> codecpar );
if ( ret < 0 )
return ret ;
/* Free existing side data*/
for ( i = 0 ; i < dst -> nb_side_data ; i ++ )
av_free ( dst -> side_data [ i ]. data );
av_freep ( & dst -> side_data );
dst -> nb_side_data = 0 ;
/* Copy side data if present */
if ( src -> nb_side_data ) {
dst -> side_data = av_mallocz_array ( src -> nb_side_data ,
sizeof ( AVPacketSideData ));
if ( ! dst -> side_data )
return AVERROR ( ENOMEM );
dst -> nb_side_data = src -> nb_side_data ;
for ( i = 0 ; i < src -> nb_side_data ; i ++ ) {
uint8_t * data = av_memdup ( src -> side_data [ i ]. data ,
src -> side_data [ i ]. size );
if ( ! data )
return AVERROR ( ENOMEM );
dst -> side_data [ i ]. type = src -> side_data [ i ]. type ;
dst -> side_data [ i ]. size = src -> side_data [ i ]. size ;
dst -> side_data [ i ]. data = data ;
}
}
return 0 ;
}
2015-11-11 14:31:10 +01:00
static void free_stream ( AVStream ** pst )
{
AVStream * st = * pst ;
int i ;
2014-03-24 13:41:49 +01:00
2015-11-11 14:31:10 +01:00
if ( ! st )
return ;
for ( i = 0 ; i < st -> nb_side_data ; i ++ )
av_freep ( & st -> side_data [ i ]. data );
2014-03-24 13:41:49 +01:00
av_freep ( & st -> side_data );
2012-08-21 06:13:54 +02:00
if ( st -> attached_pic . data )
2015-10-27 14:28:56 +01:00
av_packet_unref ( & st -> attached_pic );
2014-07-20 08:40:35 +00:00
2014-06-18 20:42:52 +02:00
if ( st -> internal ) {
2021-05-13 22:06:02 +02:00
av_parser_close ( st -> internal -> parser );
2014-06-18 20:42:52 +02:00
avcodec_free_context ( & st -> internal -> avctx );
2020-04-18 10:49:54 +02:00
av_bsf_free ( & st -> internal -> bsfc );
2017-11-05 14:59:47 -03:00
av_freep ( & st -> internal -> priv_pts );
2020-10-09 09:22:36 +02:00
av_freep ( & st -> internal -> index_entries );
2020-10-09 09:22:36 +02:00
av_freep ( & st -> internal -> probe_data . buf );
2017-03-24 18:42:19 -03:00
av_bsf_free ( & st -> internal -> extract_extradata . bsf );
2020-10-09 08:15:27 +02:00
if ( st -> internal -> info )
av_freep ( & st -> internal -> info -> duration_error );
av_freep ( & st -> internal -> info );
2014-06-18 20:42:52 +02:00
}
2015-10-07 15:51:11 +02:00
av_freep ( & st -> internal );
2012-08-21 06:13:54 +02:00
av_dict_free ( & st -> metadata );
2014-06-18 20:42:52 +02:00
avcodec_parameters_free ( & st -> codecpar );
2012-08-21 06:13:54 +02:00
av_freep ( & st -> priv_data );
2015-11-11 14:31:10 +01:00
av_freep ( pst );
}
void ff_free_stream ( AVFormatContext * s , AVStream * st )
{
av_assert0 ( s -> nb_streams > 0 );
av_assert0 ( s -> streams [ s -> nb_streams - 1 ] == st );
free_stream ( & s -> streams [ -- s -> nb_streams ]);
2012-08-21 06:13:54 +02:00
}
2011-02-04 12:04:16 +02:00
void avformat_free_context ( AVFormatContext * s )
{
int i ;
2012-10-20 19:48:26 +02:00
if ( ! s )
return ;
2019-10-18 23:23:32 -03:00
if ( s -> oformat && s -> oformat -> deinit && s -> internal -> initialized )
s -> oformat -> deinit ( s );
2011-06-05 13:18:17 +02:00
av_opt_free ( s );
2011-06-06 13:14:05 +02:00
if ( s -> iformat && s -> iformat -> priv_class && s -> priv_data )
2011-06-05 13:18:17 +02:00
av_opt_free ( s -> priv_data );
2014-04-09 22:43:48 +02:00
if ( s -> oformat && s -> oformat -> priv_class && s -> priv_data )
av_opt_free ( s -> priv_data );
2011-06-05 13:18:17 +02:00
2020-02-15 14:52:47 +01:00
for ( i = 0 ; i < s -> nb_streams ; i ++ )
free_stream ( & s -> streams [ i ]);
s -> nb_streams = 0 ;
2011-06-05 13:18:17 +02:00
2020-02-15 14:52:47 +01:00
for ( i = 0 ; i < s -> nb_programs ; i ++ ) {
2011-05-22 12:46:29 +02:00
av_dict_free ( & s -> programs [ i ] -> metadata );
2007-10-20 08:25:13 +00:00
av_freep ( & s -> programs [ i ] -> stream_index );
2007-09-25 20:45:46 +00:00
av_freep ( & s -> programs [ i ]);
}
2020-02-15 14:52:47 +01:00
s -> nb_programs = 0 ;
2008-04-24 23:09:28 +00:00
av_freep ( & s -> programs );
2002-05-24 02:09:40 +00:00
av_freep ( & s -> priv_data );
2014-01-16 01:53:03 +01:00
while ( s -> nb_chapters -- ) {
2011-05-22 12:46:29 +02:00
av_dict_free ( & s -> chapters [ s -> nb_chapters ] -> metadata );
2011-10-01 01:29:30 +02:00
av_freep ( & s -> chapters [ s -> nb_chapters ]);
2008-05-22 22:00:21 +00:00
}
av_freep ( & s -> chapters );
2011-05-22 12:46:29 +02:00
av_dict_free ( & s -> metadata );
2017-01-28 17:25:27 +01:00
av_dict_free ( & s -> internal -> id3v2_meta );
2021-01-30 15:04:24 -03:00
av_packet_free ( & s -> internal -> pkt );
2021-01-31 13:05:49 -03:00
av_packet_free ( & s -> internal -> parse_pkt );
2011-04-20 12:03:55 +03:00
av_freep ( & s -> streams );
2014-08-15 19:48:28 +02:00
flush_packet_queue ( s );
2017-07-18 11:26:39 -07:00
av_freep ( & s -> internal );
2017-12-29 01:01:37 +01:00
av_freep ( & s -> url );
2002-05-18 23:11:09 +00:00
av_free ( s );
2001-07-22 14:18:56 +00:00
}
2011-12-11 10:34:08 +01:00
void avformat_close_input ( AVFormatContext ** ps )
{
2013-09-03 22:22:19 +02:00
AVFormatContext * s ;
AVIOContext * pb ;
if ( ! ps || !* ps )
return ;
2014-01-26 23:35:38 +01:00
s = * ps ;
2013-09-03 22:22:19 +02:00
pb = s -> pb ;
2012-09-04 16:05:28 +02:00
2014-09-13 22:56:05 +02:00
if (( s -> iformat && strcmp ( s -> iformat -> name , "image2" ) && s -> iformat -> flags & AVFMT_NOFILE ) ||
2012-09-04 16:05:28 +02:00
( s -> flags & AVFMT_FLAG_CUSTOM_IO ))
pb = NULL ;
2011-12-11 10:01:46 +01:00
flush_packet_queue ( s );
2012-09-04 16:05:28 +02:00
2014-01-16 01:53:03 +01:00
if ( s -> iformat )
2012-09-04 16:05:28 +02:00
if ( s -> iformat -> read_close )
s -> iformat -> read_close ( s );
2011-12-11 10:01:46 +01:00
avformat_free_context ( s );
2012-09-04 16:05:28 +02:00
2011-12-11 10:34:08 +01:00
* ps = NULL ;
2012-09-10 07:07:56 +02:00
avio_close ( pb );
2007-12-19 14:07:13 +00:00
}
2012-10-24 14:29:05 +00:00
AVStream * avformat_new_stream ( AVFormatContext * s , const AVCodec * c )
2002-05-20 16:28:47 +00:00
{
AVStream * st ;
2006-08-30 21:18:17 +00:00
int i ;
2013-09-11 12:13:44 +02:00
AVStream ** streams ;
2001-07-22 14:18:56 +00:00
2021-03-24 01:14:24 +01:00
if ( s -> nb_streams >= s -> max_streams ) {
av_log ( s , AV_LOG_ERROR , "Number of streams exceeds max_streams parameter"
" (%d), see the documentation if you wish to increase it \n " ,
s -> max_streams );
2010-10-06 20:56:14 +00:00
return NULL ;
2016-12-10 20:15:13 +01:00
}
2013-09-11 13:34:25 +02:00
streams = av_realloc_array ( s -> streams , s -> nb_streams + 1 , sizeof ( * streams ));
2013-09-11 12:13:44 +02:00
if ( ! streams )
return NULL ;
s -> streams = streams ;
2002-05-20 16:28:47 +00:00
st = av_mallocz ( sizeof ( AVStream ));
if ( ! st )
return NULL ;
2005-12-17 18:14:38 +00:00
2015-10-07 15:51:11 +02:00
st -> internal = av_mallocz ( sizeof ( * st -> internal ));
if ( ! st -> internal )
goto fail ;
2020-10-09 08:15:27 +02:00
st -> internal -> info = av_mallocz ( sizeof ( * st -> internal -> info ));
if ( ! st -> internal -> info )
goto fail ;
st -> internal -> info -> last_dts = AV_NOPTS_VALUE ;
2016-04-10 20:58:15 +01:00
st -> codecpar = avcodec_parameters_alloc ();
if ( ! st -> codecpar )
goto fail ;
st -> internal -> avctx = avcodec_alloc_context3 ( NULL );
if ( ! st -> internal -> avctx )
goto fail ;
2014-05-18 12:12:59 +02:00
if ( s -> iformat ) {
/* default pts setting is MPEG-like */
avpriv_set_pts_info ( st , 33 , 1 , 90000 );
2015-10-07 11:48:28 +02:00
/* we set the current DTS to 0 so that formats without any timestamps
* but durations get some timestamps, formats with some unknown
* timestamps have their first few packets buffered and the
* timestamps corrected before they are returned to the user */
2021-06-05 11:12:03 -03:00
st -> internal -> cur_dts = RELATIVE_TS_BASE ;
2015-10-07 11:48:28 +02:00
} else {
2021-06-05 11:12:03 -03:00
st -> internal -> cur_dts = AV_NOPTS_VALUE ;
2014-05-18 12:12:59 +02:00
}
2014-01-16 01:53:03 +01:00
st -> index = s -> nb_streams ;
2003-08-08 18:02:23 +00:00
st -> start_time = AV_NOPTS_VALUE ;
2014-01-16 01:53:03 +01:00
st -> duration = AV_NOPTS_VALUE ;
2021-06-05 11:12:03 -03:00
st -> internal -> first_dts = AV_NOPTS_VALUE ;
2021-05-01 23:13:41 -03:00
st -> internal -> probe_packets = s -> max_probe_packets ;
2020-10-09 09:22:36 +02:00
st -> internal -> pts_wrap_reference = AV_NOPTS_VALUE ;
st -> internal -> pts_wrap_behavior = AV_PTS_WRAP_IGNORE ;
2004-05-21 20:43:21 +00:00
2021-05-01 23:05:21 -03:00
st -> internal -> last_IP_pts = AV_NOPTS_VALUE ;
2020-10-09 09:22:36 +02:00
st -> internal -> last_dts_for_order_check = AV_NOPTS_VALUE ;
2014-01-16 01:53:03 +01:00
for ( i = 0 ; i < MAX_REORDER_DELAY + 1 ; i ++ )
2020-10-09 09:22:36 +02:00
st -> internal -> pts_buffer [ i ] = AV_NOPTS_VALUE ;
2004-05-21 20:43:21 +00:00
2014-01-16 01:53:03 +01:00
st -> sample_aspect_ratio = ( AVRational ) { 0 , 1 };
2008-08-23 23:13:58 +00:00
2012-08-11 20:06:08 +03:00
#if FF_API_R_FRAME_RATE
2020-10-09 08:15:27 +02:00
st -> internal -> info -> last_dts = AV_NOPTS_VALUE ;
2012-08-11 20:06:08 +03:00
#endif
2020-10-09 08:15:27 +02:00
st -> internal -> info -> fps_first_dts = AV_NOPTS_VALUE ;
st -> internal -> info -> fps_last_dts = AV_NOPTS_VALUE ;
2012-08-11 20:06:08 +03:00
2020-10-09 09:22:36 +02:00
st -> internal -> inject_global_side_data = s -> internal -> inject_global_side_data ;
2014-04-13 19:20:17 +02:00
2016-04-10 20:58:15 +01:00
st -> internal -> need_context_update = 1 ;
2014-06-18 20:42:52 +02:00
2002-05-20 16:28:47 +00:00
s -> streams [ s -> nb_streams ++ ] = st ;
return st ;
2015-10-07 15:51:11 +02:00
fail :
free_stream ( & st );
return NULL ;
2002-05-20 16:28:47 +00:00
}
2007-09-25 20:45:46 +00:00
AVProgram * av_new_program ( AVFormatContext * ac , int id )
{
2014-01-16 01:53:03 +01:00
AVProgram * program = NULL ;
2021-04-01 18:18:13 +02:00
int i , ret ;
2007-09-25 20:45:46 +00:00
2015-03-16 08:57:35 +00:00
av_log ( ac , AV_LOG_TRACE , "new_program: id=0x%04x \n " , id );
2007-09-25 20:45:46 +00:00
2014-01-16 01:53:03 +01:00
for ( i = 0 ; i < ac -> nb_programs ; i ++ )
if ( ac -> programs [ i ] -> id == id )
2007-09-25 20:45:46 +00:00
program = ac -> programs [ i ];
2014-01-16 01:53:03 +01:00
if ( ! program ) {
2007-09-25 20:45:46 +00:00
program = av_mallocz ( sizeof ( AVProgram ));
if ( ! program )
return NULL ;
2021-04-01 18:18:13 +02:00
ret = av_dynarray_add_nofree ( & ac -> programs , & ac -> nb_programs , program );
if ( ret < 0 ) {
av_free ( program );
return NULL ;
}
2007-09-25 20:45:46 +00:00
program -> discard = AVDISCARD_NONE ;
2018-05-17 15:30:21 -07:00
program -> pmt_version = - 1 ;
2020-12-27 20:32:54 +01:00
program -> id = id ;
program -> pts_wrap_reference = AV_NOPTS_VALUE ;
program -> pts_wrap_behavior = AV_PTS_WRAP_IGNORE ;
program -> start_time =
program -> end_time = AV_NOPTS_VALUE ;
2007-09-25 20:45:46 +00:00
}
return program ;
}
2021-03-16 08:29:59 +01:00
AVChapter * avpriv_new_chapter ( AVFormatContext * s , int64_t id , AVRational time_base ,
2014-01-16 01:53:03 +01:00
int64_t start , int64_t end , const char * title )
2008-05-22 22:00:21 +00:00
{
2008-05-23 13:02:27 +00:00
AVChapter * chapter = NULL ;
2021-04-01 18:18:13 +02:00
int i , ret ;
2008-05-23 13:02:27 +00:00
2014-05-23 04:33:05 +02:00
if ( end != AV_NOPTS_VALUE && start > end ) {
av_log ( s , AV_LOG_ERROR , "Chapter end time %" PRId64 " before start %" PRId64 " \n " , end , start );
return NULL ;
}
2021-01-06 23:24:49 +01:00
if ( ! s -> nb_chapters ) {
s -> internal -> chapter_ids_monotonic = 1 ;
} else if ( ! s -> internal -> chapter_ids_monotonic || s -> chapters [ s -> nb_chapters - 1 ] -> id >= id ) {
s -> internal -> chapter_ids_monotonic = 0 ;
for ( i = 0 ; i < s -> nb_chapters ; i ++ )
if ( s -> chapters [ i ] -> id == id )
chapter = s -> chapters [ i ];
}
2008-05-23 13:02:27 +00:00
2014-01-16 01:53:03 +01:00
if ( ! chapter ) {
chapter = av_mallocz ( sizeof ( AVChapter ));
if ( ! chapter )
2008-05-23 13:14:11 +00:00
return NULL ;
2021-04-01 18:18:13 +02:00
ret = av_dynarray_add_nofree ( & s -> chapters , & s -> nb_chapters , chapter );
if ( ret < 0 ) {
av_free ( chapter );
return NULL ;
}
2008-05-23 13:02:27 +00:00
}
2011-05-22 12:46:29 +02:00
av_dict_set ( & chapter -> metadata , "title" , title , 0 );
2014-01-16 01:53:03 +01:00
chapter -> id = id ;
chapter -> time_base = time_base ;
chapter -> start = start ;
chapter -> end = end ;
2008-05-22 22:00:21 +00:00
2008-05-23 13:14:11 +00:00
return chapter ;
2008-05-22 22:00:21 +00:00
}
2007-09-25 20:45:46 +00:00
2015-12-10 20:59:40 +01:00
void av_program_add_stream_index ( AVFormatContext * ac , int progid , unsigned idx )
2007-10-20 08:25:13 +00:00
{
int i , j ;
2014-01-16 01:53:03 +01:00
AVProgram * program = NULL ;
2013-09-11 12:13:44 +02:00
void * tmp ;
2007-10-20 08:25:13 +00:00
2009-10-19 18:55:27 +00:00
if ( idx >= ac -> nb_streams ) {
av_log ( ac , AV_LOG_ERROR , "stream index %d is not valid \n " , idx );
return ;
}
2014-01-16 01:53:03 +01:00
for ( i = 0 ; i < ac -> nb_programs ; i ++ ) {
if ( ac -> programs [ i ] -> id != progid )
2007-10-20 08:25:13 +00:00
continue ;
program = ac -> programs [ i ];
2014-01-16 01:53:03 +01:00
for ( j = 0 ; j < program -> nb_stream_indexes ; j ++ )
if ( program -> stream_index [ j ] == idx )
2007-10-20 08:25:13 +00:00
return ;
2013-09-11 13:34:25 +02:00
tmp = av_realloc_array ( program -> stream_index , program -> nb_stream_indexes + 1 , sizeof ( unsigned int ));
2014-01-26 23:35:38 +01:00
if ( ! tmp )
2007-10-20 08:25:13 +00:00
return ;
2013-09-11 12:13:44 +02:00
program -> stream_index = tmp ;
2007-10-20 08:25:13 +00:00
program -> stream_index [ program -> nb_stream_indexes ++ ] = idx ;
return ;
}
}
2020-01-16 16:25:26 -03:00
uint64_t ff_ntp_time ( void )
2010-03-10 22:21:39 +00:00
{
2020-01-16 16:25:26 -03:00
return ( av_gettime () / 1000 ) * 1000 + NTP_OFFSET_US ;
2010-03-10 22:21:39 +00:00
}
2018-05-07 15:27:36 +05:30
uint64_t ff_get_formatted_ntp_time ( uint64_t ntp_time_us )
{
uint64_t ntp_ts , frac_part , sec ;
uint32_t usec ;
//current ntp time in seconds and micro seconds
sec = ntp_time_us / 1000000 ;
usec = ntp_time_us % 1000000 ;
//encoding in ntp timestamp format
frac_part = usec * 0xFFFFFFFFULL ;
frac_part /= 1000000 ;
if ( sec > 0xFFFFFFFFULL )
av_log ( NULL , AV_LOG_WARNING , "NTP time format roll over detected \n " );
ntp_ts = sec << 32 ;
ntp_ts |= frac_part ;
return ntp_ts ;
}
2021-03-23 14:29:48 -07:00
uint64_t ff_parse_ntp_time ( uint64_t ntp_ts )
{
uint64_t sec = ntp_ts >> 32 ;
uint64_t frac_part = ntp_ts & 0xFFFFFFFFULL ;
uint64_t usec = ( frac_part * 1000000 ) / 0xFFFFFFFFULL ;
return ( sec * 1000000 ) + usec ;
}
2016-11-01 22:58:01 +01:00
int av_get_frame_filename2 ( char * buf , int buf_size , const char * path , int number , int flags )
2001-09-16 21:50:48 +00:00
{
const char * p ;
2003-10-26 10:49:49 +00:00
char * q , buf1 [ 20 ], c ;
2016-11-01 22:58:01 +01:00
int nd , len , percentd_found ;
2001-09-16 21:50:48 +00:00
q = buf ;
p = path ;
percentd_found = 0 ;
2014-01-16 01:53:03 +01:00
for (;;) {
2001-09-16 21:50:48 +00:00
c = * p ++ ;
if ( c == '\0' )
break ;
if ( c == '%' ) {
2002-12-11 03:20:05 +00:00
do {
nd = 0 ;
2020-08-15 22:52:42 +02:00
while ( av_isdigit ( * p )) {
if ( nd >= INT_MAX / 10 - 255 )
goto fail ;
2002-12-11 03:20:05 +00:00
nd = nd * 10 + * p ++ - '0' ;
2020-08-15 22:52:42 +02:00
}
2002-12-11 03:20:05 +00:00
c = * p ++ ;
2013-03-03 11:17:50 +01:00
} while ( av_isdigit ( c ));
2002-12-11 03:20:05 +00:00
2014-01-16 01:53:03 +01:00
switch ( c ) {
2001-09-16 21:50:48 +00:00
case '%' :
goto addchar ;
case 'd' :
2016-08-03 20:34:20 +02:00
if ( ! ( flags & AV_FRAME_FILENAME_FLAGS_MULTIPLE ) && percentd_found )
2001-09-16 21:50:48 +00:00
goto fail ;
percentd_found = 1 ;
2015-02-04 13:01:25 +01:00
if ( number < 0 )
2015-02-03 09:01:29 -08:00
nd += 1 ;
2001-09-16 21:50:48 +00:00
snprintf ( buf1 , sizeof ( buf1 ), "%0*d" , nd , number );
len = strlen ( buf1 );
if (( q - buf + len ) > buf_size - 1 )
goto fail ;
memcpy ( q , buf1 , len );
q += len ;
break ;
default :
goto fail ;
}
} else {
2014-01-16 01:53:03 +01:00
addchar :
2001-09-16 21:50:48 +00:00
if (( q - buf ) < buf_size - 1 )
* q ++ = c ;
}
}
2016-11-01 22:58:01 +01:00
if ( ! percentd_found )
2001-09-16 21:50:48 +00:00
goto fail ;
* q = '\0' ;
return 0 ;
2014-01-16 01:53:03 +01:00
fail :
2001-09-16 21:50:48 +00:00
* q = '\0' ;
return - 1 ;
}
2016-08-03 20:34:20 +02:00
int av_get_frame_filename ( char * buf , int buf_size , const char * path , int number )
{
2016-11-01 22:58:01 +01:00
return av_get_frame_filename2 ( buf , buf_size , path , number , 0 );
2016-08-03 20:34:20 +02:00
}
2010-06-27 14:16:46 +00:00
void av_url_split ( char * proto , int proto_size ,
char * authorization , int authorization_size ,
char * hostname , int hostname_size ,
2014-01-16 01:53:03 +01:00
int * port_ptr , char * path , int path_size , const char * url )
2002-07-24 18:04:50 +00:00
{
2020-02-03 01:32:00 +01:00
const char * p , * ls , * at , * at2 , * col , * brk ;
2002-07-24 18:04:50 +00:00
2014-01-16 01:53:03 +01:00
if ( port_ptr )
* port_ptr = - 1 ;
if ( proto_size > 0 )
proto [ 0 ] = 0 ;
if ( authorization_size > 0 )
authorization [ 0 ] = 0 ;
if ( hostname_size > 0 )
hostname [ 0 ] = 0 ;
if ( path_size > 0 )
path [ 0 ] = 0 ;
2002-07-24 18:04:50 +00:00
2007-09-27 19:18:07 +00:00
/* parse protocol */
if (( p = strchr ( url , ':' ))) {
av_strlcpy ( proto , url , FFMIN ( proto_size , p + 1 - url ));
p ++ ; /* skip ':' */
2014-01-16 01:53:03 +01:00
if ( * p == '/' )
p ++ ;
if ( * p == '/' )
p ++ ;
2002-07-24 18:04:50 +00:00
} else {
2007-09-27 19:18:07 +00:00
/* no protocol means plain filename */
av_strlcpy ( path , url , path_size );
return ;
}
2004-08-12 00:09:32 +00:00
2007-09-27 19:18:07 +00:00
/* separate path from hostname */
2020-02-03 01:32:00 +01:00
ls = p + strcspn ( p , "/?#" );
av_strlcpy ( path , ls , path_size );
2004-08-12 00:09:32 +00:00
2007-09-27 19:18:07 +00:00
/* the rest is hostname, use that to parse auth/port */
if ( ls != p ) {
/* authorization (user[:pass]@hostname) */
2012-11-15 10:56:47 +00:00
at2 = p ;
while (( at = strchr ( p , '@' )) && at < ls ) {
av_strlcpy ( authorization , at2 ,
FFMIN ( authorization_size , at + 1 - at2 ));
2007-09-27 19:18:07 +00:00
p = at + 1 ; /* skip '@' */
}
2004-08-12 00:09:32 +00:00
2007-09-29 14:35:52 +00:00
if ( * p == '[' && ( brk = strchr ( p , ']' )) && brk < ls ) {
/* [host]:port */
av_strlcpy ( hostname , p + 1 ,
FFMIN ( hostname_size , brk - p ));
if ( brk [ 1 ] == ':' && port_ptr )
* port_ptr = atoi ( brk + 2 );
} else if (( col = strchr ( p , ':' )) && col < ls ) {
av_strlcpy ( hostname , p ,
FFMIN ( col + 1 - p , hostname_size ));
2014-01-16 01:53:03 +01:00
if ( port_ptr )
* port_ptr = atoi ( col + 1 );
2007-09-29 14:35:52 +00:00
} else
av_strlcpy ( hostname , p ,
FFMIN ( ls + 1 - p , hostname_size ));
2002-07-24 18:04:50 +00:00
}
}
2018-09-22 22:10:09 +08:00
int ff_mkdir_p ( const char * path )
{
int ret = 0 ;
char * temp = av_strdup ( path );
char * pos = temp ;
char tmp_ch = '\0' ;
if ( ! path || ! temp ) {
return - 1 ;
}
if ( ! av_strncasecmp ( temp , "/" , 1 ) || ! av_strncasecmp ( temp , " \\ " , 1 )) {
pos ++ ;
} else if ( ! av_strncasecmp ( temp , "./" , 2 ) || ! av_strncasecmp ( temp , ". \\ " , 2 )) {
pos += 2 ;
}
for ( ; * pos != '\0' ; ++ pos ) {
if ( * pos == '/' || * pos == '\\' ) {
tmp_ch = * pos ;
* pos = '\0' ;
ret = mkdir ( temp , 0755 );
* pos = tmp_ch ;
}
}
if (( * ( pos - 1 ) != '/' ) || ( * ( pos - 1 ) != '\\' )) {
ret = mkdir ( temp , 0755 );
}
av_free ( temp );
return ret ;
}
2010-03-25 07:13:20 +00:00
char * ff_data_to_hex ( char * buff , const uint8_t * src , int s , int lowercase )
2008-08-27 23:43:28 +00:00
{
int i ;
2010-03-25 07:13:20 +00:00
static const char hex_table_uc [ 16 ] = { '0' , '1' , '2' , '3' ,
2010-03-25 07:14:41 +00:00
'4' , '5' , '6' , '7' ,
'8' , '9' , 'A' , 'B' ,
'C' , 'D' , 'E' , 'F' };
2010-03-25 07:13:20 +00:00
static const char hex_table_lc [ 16 ] = { '0' , '1' , '2' , '3' ,
'4' , '5' , '6' , '7' ,
'8' , '9' , 'a' , 'b' ,
'c' , 'd' , 'e' , 'f' };
const char * hex_table = lowercase ? hex_table_lc : hex_table_uc ;
2008-08-27 23:43:28 +00:00
2014-01-16 01:53:03 +01:00
for ( i = 0 ; i < s ; i ++ ) {
2008-08-28 12:00:58 +00:00
buff [ i * 2 ] = hex_table [ src [ i ] >> 4 ];
buff [ i * 2 + 1 ] = hex_table [ src [ i ] & 0xF ];
2008-08-27 23:43:28 +00:00
}
return buff ;
}
2010-08-09 10:05:33 +00:00
int ff_hex_to_data ( uint8_t * data , const char * p )
{
int c , len , v ;
len = 0 ;
2014-01-16 01:53:03 +01:00
v = 1 ;
2010-08-09 10:05:33 +00:00
for (;;) {
p += strspn ( p , SPACE_CHARS );
if ( * p == '\0' )
break ;
2013-03-03 11:17:50 +01:00
c = av_toupper (( unsigned char ) * p ++ );
2010-08-09 10:05:33 +00:00
if ( c >= '0' && c <= '9' )
c = c - '0' ;
else if ( c >= 'A' && c <= 'F' )
c = c - 'A' + 10 ;
else
break ;
v = ( v << 4 ) | c ;
if ( v & 0x100 ) {
if ( data )
data [ len ] = v ;
len ++ ;
v = 1 ;
}
}
return len ;
}
2011-11-29 19:28:15 +01:00
void avpriv_set_pts_info ( AVStream * s , int pts_wrap_bits ,
unsigned int pts_num , unsigned int pts_den )
2002-10-21 15:54:49 +00:00
{
2011-02-06 15:27:30 +01:00
AVRational new_tb ;
2014-01-16 01:53:03 +01:00
if ( av_reduce ( & new_tb . num , & new_tb . den , pts_num , pts_den , INT_MAX )) {
if ( new_tb . num != pts_num )
av_log ( NULL , AV_LOG_DEBUG ,
"st:%d removing common factor %d from timebase \n " ,
s -> index , pts_num / new_tb . num );
} else
av_log ( NULL , AV_LOG_WARNING ,
"st:%d has too large timebase, reducing \n " , s -> index );
2009-07-02 12:47:58 +00:00
2014-01-16 01:53:03 +01:00
if ( new_tb . num <= 0 || new_tb . den <= 0 ) {
av_log ( NULL , AV_LOG_ERROR ,
2014-01-26 23:35:38 +01:00
"Ignoring attempt to set invalid timebase %d/%d for st:%d \n " ,
new_tb . num , new_tb . den ,
2014-01-16 01:53:03 +01:00
s -> index );
2011-02-06 15:27:30 +01:00
return ;
}
2014-01-16 01:53:03 +01:00
s -> time_base = new_tb ;
2017-11-13 00:11:52 -03:00
s -> internal -> avctx -> pkt_timebase = new_tb ;
2011-02-06 15:27:30 +01:00
s -> pts_wrap_bits = pts_wrap_bits ;
2002-10-21 15:54:49 +00:00
}
2010-03-05 22:31:45 +00:00
2010-08-19 14:49:53 +00:00
void ff_parse_key_value ( const char * str , ff_parse_key_val_cb callback_get_buf ,
void * context )
{
const char * ptr = str ;
/* Parse key=value pairs. */
for (;;) {
const char * key ;
char * dest = NULL , * dest_end ;
int key_len , dest_len = 0 ;
/* Skip whitespace and potential commas. */
2013-03-03 11:17:50 +01:00
while ( * ptr && ( av_isspace ( * ptr ) || * ptr == ',' ))
2010-08-19 14:49:53 +00:00
ptr ++ ;
if ( !* ptr )
break ;
key = ptr ;
if ( ! ( ptr = strchr ( key , '=' )))
break ;
ptr ++ ;
key_len = ptr - key ;
callback_get_buf ( context , key , key_len , & dest , & dest_len );
dest_end = dest + dest_len - 1 ;
if ( * ptr == '\"' ) {
ptr ++ ;
while ( * ptr && * ptr != '\"' ) {
if ( * ptr == '\\' ) {
if ( ! ptr [ 1 ])
break ;
if ( dest && dest < dest_end )
* dest ++ = ptr [ 1 ];
ptr += 2 ;
} else {
if ( dest && dest < dest_end )
* dest ++ = * ptr ;
ptr ++ ;
}
}
if ( * ptr == '\"' )
ptr ++ ;
} else {
2013-03-03 11:17:50 +01:00
for (; * ptr && ! ( av_isspace ( * ptr ) || * ptr == ',' ); ptr ++ )
2010-08-19 14:49:53 +00:00
if ( dest && dest < dest_end )
* dest ++ = * ptr ;
}
if ( dest )
* dest = 0 ;
}
}
2010-12-26 01:24:51 +00:00
int ff_find_stream_index ( AVFormatContext * s , int id )
{
int i ;
2014-01-16 01:53:03 +01:00
for ( i = 0 ; i < s -> nb_streams ; i ++ )
2010-12-26 01:24:51 +00:00
if ( s -> streams [ i ] -> id == id )
return i ;
return - 1 ;
}
2011-03-17 12:24:23 +02:00
2014-07-26 02:50:59 -07:00
int avformat_query_codec ( const AVOutputFormat * ofmt , enum AVCodecID codec_id ,
2014-01-16 01:53:03 +01:00
int std_compliance )
2011-08-11 20:34:45 +02:00
{
if ( ofmt ) {
2015-05-28 12:31:40 +02:00
unsigned int codec_tag ;
2011-08-11 20:34:45 +02:00
if ( ofmt -> query_codec )
return ofmt -> query_codec ( codec_id , std_compliance );
else if ( ofmt -> codec_tag )
2015-05-28 12:31:40 +02:00
return !! av_codec_get_tag2 ( ofmt -> codec_tag , codec_id , & codec_tag );
2014-01-16 01:53:03 +01:00
else if ( codec_id == ofmt -> video_codec ||
codec_id == ofmt -> audio_codec ||
2016-08-23 12:03:20 +03:00
codec_id == ofmt -> subtitle_codec ||
codec_id == ofmt -> data_codec )
2011-08-22 18:47:24 -07:00
return 1 ;
2011-08-11 20:34:45 +02:00
}
return AVERROR_PATCHWELCOME ;
}
2011-11-01 13:40:04 +02:00
int avformat_network_init ( void )
{
#if CONFIG_NETWORK
int ret ;
if (( ret = ff_network_init ()) < 0 )
return ret ;
2015-01-22 15:50:48 +01:00
if (( ret = ff_tls_init ()) < 0 )
return ret ;
2011-11-01 13:40:04 +02:00
#endif
return 0 ;
}
int avformat_network_deinit ( void )
{
#if CONFIG_NETWORK
ff_network_close ();
ff_tls_deinit ();
#endif
return 0 ;
}
2011-12-16 12:48:09 +02:00
int ff_add_param_change ( AVPacket * pkt , int32_t channels ,
uint64_t channel_layout , int32_t sample_rate ,
int32_t width , int32_t height )
{
uint32_t flags = 0 ;
int size = 4 ;
uint8_t * data ;
if ( ! pkt )
return AVERROR ( EINVAL );
if ( channels ) {
2014-01-16 01:53:03 +01:00
size += 4 ;
2011-12-16 12:48:09 +02:00
flags |= AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT ;
}
if ( channel_layout ) {
2014-01-16 01:53:03 +01:00
size += 8 ;
2011-12-16 12:48:09 +02:00
flags |= AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT ;
}
if ( sample_rate ) {
2014-01-16 01:53:03 +01:00
size += 4 ;
2011-12-16 12:48:09 +02:00
flags |= AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE ;
}
if ( width || height ) {
2014-01-16 01:53:03 +01:00
size += 8 ;
2011-12-16 12:48:09 +02:00
flags |= AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS ;
}
data = av_packet_new_side_data ( pkt , AV_PKT_DATA_PARAM_CHANGE , size );
if ( ! data )
return AVERROR ( ENOMEM );
bytestream_put_le32 ( & data , flags );
if ( channels )
bytestream_put_le32 ( & data , channels );
if ( channel_layout )
bytestream_put_le64 ( & data , channel_layout );
if ( sample_rate )
bytestream_put_le32 ( & data , sample_rate );
if ( width || height ) {
bytestream_put_le32 ( & data , width );
bytestream_put_le32 ( & data , height );
}
return 0 ;
}
2012-01-27 13:33:09 +01:00
2012-05-07 20:27:08 +02:00
AVRational av_guess_sample_aspect_ratio ( AVFormatContext * format , AVStream * stream , AVFrame * frame )
{
AVRational undef = { 0 , 1 };
AVRational stream_sample_aspect_ratio = stream ? stream -> sample_aspect_ratio : undef ;
2016-04-10 20:58:15 +01:00
AVRational codec_sample_aspect_ratio = stream && stream -> codecpar ? stream -> codecpar -> sample_aspect_ratio : undef ;
2012-05-20 15:53:02 +02:00
AVRational frame_sample_aspect_ratio = frame ? frame -> sample_aspect_ratio : codec_sample_aspect_ratio ;
2012-05-07 20:27:08 +02:00
av_reduce ( & stream_sample_aspect_ratio . num , & stream_sample_aspect_ratio . den ,
stream_sample_aspect_ratio . num , stream_sample_aspect_ratio . den , INT_MAX );
if ( stream_sample_aspect_ratio . num <= 0 || stream_sample_aspect_ratio . den <= 0 )
stream_sample_aspect_ratio = undef ;
av_reduce ( & frame_sample_aspect_ratio . num , & frame_sample_aspect_ratio . den ,
frame_sample_aspect_ratio . num , frame_sample_aspect_ratio . den , INT_MAX );
if ( frame_sample_aspect_ratio . num <= 0 || frame_sample_aspect_ratio . den <= 0 )
frame_sample_aspect_ratio = undef ;
if ( stream_sample_aspect_ratio . num )
return stream_sample_aspect_ratio ;
else
return frame_sample_aspect_ratio ;
}
2012-07-18 11:41:13 +02:00
2013-03-27 22:08:53 +01:00
AVRational av_guess_frame_rate ( AVFormatContext * format , AVStream * st , AVFrame * frame )
{
AVRational fr = st -> r_frame_rate ;
2016-04-10 20:58:15 +01:00
AVRational codec_fr = st -> internal -> avctx -> framerate ;
2014-02-19 18:20:13 +01:00
AVRational avg_fr = st -> avg_frame_rate ;
if ( avg_fr . num > 0 && avg_fr . den > 0 && fr . num > 0 && fr . den > 0 &&
av_q2d ( avg_fr ) < 70 && av_q2d ( fr ) > 210 ) {
fr = avg_fr ;
}
2013-03-27 22:08:53 +01:00
2016-04-10 20:58:15 +01:00
if ( st -> internal -> avctx -> ticks_per_frame > 1 ) {
2015-02-09 21:14:22 +01:00
if ( codec_fr . num > 0 && codec_fr . den > 0 &&
( fr . num == 0 || av_q2d ( codec_fr ) < av_q2d ( fr ) * 0.7 && fabs ( 1.0 - av_q2d ( av_div_q ( avg_fr , fr ))) > 0.1 ))
2013-03-27 22:08:53 +01:00
fr = codec_fr ;
}
return fr ;
}
2019-02-05 00:16:36 +01:00
/**
* Matches a stream specifier (but ignores requested index).
*
2019-02-16 18:10:13 +01:00
* @param indexptr set to point to the requested stream index if there is one
2019-02-05 00:16:36 +01:00
*
* @return <0 on error
* 0 if st is NOT a matching stream
* >0 if st is a matching stream
*/
static int match_stream_specifier ( AVFormatContext * s , AVStream * st ,
2019-05-19 00:43:29 +02:00
const char * spec , const char ** indexptr , AVProgram ** p )
2012-07-18 11:41:13 +02:00
{
2019-02-16 18:47:59 +01:00
int match = 1 ; /* Stores if the specifier matches so far. */
2019-02-16 18:10:13 +01:00
while ( * spec ) {
2019-02-16 18:56:56 +01:00
if ( * spec <= '9' && * spec >= '0' ) { /* opt:index */
if ( indexptr )
* indexptr = spec ;
return match ;
} else if ( * spec == 'v' || * spec == 'a' || * spec == 's' || * spec == 'd' ||
* spec == 't' || * spec == 'V' ) { /* opt:[vasdtV] */
enum AVMediaType type ;
int nopic = 0 ;
2012-07-18 11:41:13 +02:00
2019-02-16 18:56:56 +01:00
switch ( * spec ++ ) {
case 'v' : type = AVMEDIA_TYPE_VIDEO ; break ;
case 'a' : type = AVMEDIA_TYPE_AUDIO ; break ;
case 's' : type = AVMEDIA_TYPE_SUBTITLE ; break ;
case 'd' : type = AVMEDIA_TYPE_DATA ; break ;
case 't' : type = AVMEDIA_TYPE_ATTACHMENT ; break ;
case 'V' : type = AVMEDIA_TYPE_VIDEO ; nopic = 1 ; break ;
default : av_assert0 ( 0 );
}
if ( * spec && * spec ++ != ':' ) /* If we are not at the end, then another specifier must follow. */
return AVERROR ( EINVAL );
2019-02-16 18:10:13 +01:00
2019-02-16 18:56:56 +01:00
if ( type != st -> codecpar -> codec_type )
match = 0 ;
if ( nopic && ( st -> disposition & AV_DISPOSITION_ATTACHED_PIC ))
match = 0 ;
} else if ( * spec == 'p' && * ( spec + 1 ) == ':' ) {
int prog_id , i , j ;
int found = 0 ;
char * endptr ;
spec += 2 ;
prog_id = strtol ( spec , & endptr , 0 );
/* Disallow empty id and make sure that if we are not at the end, then another specifier must follow. */
if ( spec == endptr || ( * endptr && * endptr ++ != ':' ))
return AVERROR ( EINVAL );
spec = endptr ;
if ( match ) {
for ( i = 0 ; i < s -> nb_programs ; i ++ ) {
if ( s -> programs [ i ] -> id != prog_id )
continue ;
2012-07-18 11:41:13 +02:00
2019-02-16 18:56:56 +01:00
for ( j = 0 ; j < s -> programs [ i ] -> nb_stream_indexes ; j ++ ) {
if ( st -> index == s -> programs [ i ] -> stream_index [ j ]) {
found = 1 ;
2019-05-19 00:43:29 +02:00
if ( p )
* p = s -> programs [ i ];
2019-02-16 18:56:56 +01:00
i = s -> nb_programs ;
break ;
}
}
2018-04-01 23:29:14 +02:00
}
2012-07-18 11:41:13 +02:00
}
2019-02-16 18:56:56 +01:00
if ( ! found )
match = 0 ;
} else if ( * spec == '#' ||
( * spec == 'i' && * ( spec + 1 ) == ':' )) {
int stream_id ;
char * endptr ;
spec += 1 + ( * spec == 'i' );
stream_id = strtol ( spec , & endptr , 0 );
if ( spec == endptr || * endptr ) /* Disallow empty id and make sure we are at the end. */
return AVERROR ( EINVAL );
return match && ( stream_id == st -> id );
} else if ( * spec == 'm' && * ( spec + 1 ) == ':' ) {
AVDictionaryEntry * tag ;
char * key , * val ;
int ret ;
2014-08-14 00:41:08 +02:00
2019-02-16 18:56:56 +01:00
if ( match ) {
spec += 2 ;
val = strchr ( spec , ':' );
2014-08-14 00:41:08 +02:00
2019-02-16 18:56:56 +01:00
key = val ? av_strndup ( spec , val - spec ) : av_strdup ( spec );
if ( ! key )
return AVERROR ( ENOMEM );
2014-08-14 00:41:08 +02:00
2019-02-16 18:56:56 +01:00
tag = av_dict_get ( st -> metadata , key , NULL , 0 );
if ( tag ) {
if ( ! val || ! strcmp ( tag -> value , val + 1 ))
ret = 1 ;
else
ret = 0 ;
} else
ret = 0 ;
2014-08-14 00:41:08 +02:00
2019-02-16 18:56:56 +01:00
av_freep ( & key );
}
return match && ret ;
} else if ( * spec == 'u' && * ( spec + 1 ) == '\0' ) {
AVCodecParameters * par = st -> codecpar ;
int val ;
switch ( par -> codec_type ) {
case AVMEDIA_TYPE_AUDIO :
val = par -> sample_rate && par -> channels ;
2021-04-18 10:59:35 -03:00
if ( par -> format == AV_SAMPLE_FMT_NONE )
2019-02-16 18:56:56 +01:00
return 0 ;
break ;
case AVMEDIA_TYPE_VIDEO :
val = par -> width && par -> height ;
2021-04-18 10:59:35 -03:00
if ( par -> format == AV_PIX_FMT_NONE )
2019-02-16 18:56:56 +01:00
return 0 ;
break ;
case AVMEDIA_TYPE_UNKNOWN :
val = 0 ;
break ;
default :
val = 1 ;
break ;
}
return match && ( par -> codec_id != AV_CODEC_ID_NONE && val != 0 );
} else {
return AVERROR ( EINVAL );
}
2019-02-16 18:10:13 +01:00
}
2012-07-18 11:41:13 +02:00
2019-02-16 18:47:59 +01:00
return match ;
2012-07-18 11:41:13 +02:00
}
2012-09-26 12:13:53 +02:00
2019-02-05 00:16:36 +01:00
int avformat_match_stream_specifier ( AVFormatContext * s , AVStream * st ,
const char * spec )
{
2019-02-16 18:10:13 +01:00
int ret , index ;
char * endptr ;
const char * indexptr = NULL ;
2019-05-19 00:43:29 +02:00
AVProgram * p = NULL ;
int nb_streams ;
2019-02-16 18:10:13 +01:00
2019-05-19 00:43:29 +02:00
ret = match_stream_specifier ( s , st , spec , & indexptr , & p );
2019-02-16 18:10:13 +01:00
if ( ret < 0 )
goto error ;
if ( ! indexptr )
return ret ;
index = strtol ( indexptr , & endptr , 0 );
if ( * endptr ) { /* We can't have anything after the requested index. */
ret = AVERROR ( EINVAL );
goto error ;
}
2019-02-05 00:16:36 +01:00
/* This is not really needed but saves us a loop for simple stream index specifiers. */
2019-02-16 18:10:13 +01:00
if ( spec == indexptr )
return ( index == st -> index );
2019-02-05 00:16:36 +01:00
/* If we requested a matching stream index, we have to ensure st is that. */
2019-05-19 00:43:29 +02:00
nb_streams = p ? p -> nb_stream_indexes : s -> nb_streams ;
for ( int i = 0 ; i < nb_streams && index >= 0 ; i ++ ) {
AVStream * candidate = p ? s -> streams [ p -> stream_index [ i ]] : s -> streams [ i ];
ret = match_stream_specifier ( s , candidate , spec , NULL , NULL );
2019-02-05 00:16:36 +01:00
if ( ret < 0 )
2019-02-16 18:10:13 +01:00
goto error ;
2019-05-19 00:43:29 +02:00
if ( ret > 0 && index -- == 0 && st == candidate )
2019-02-05 00:16:36 +01:00
return 1 ;
}
return 0 ;
2019-02-16 18:10:13 +01:00
error :
if ( ret == AVERROR ( EINVAL ))
av_log ( s , AV_LOG_ERROR , "Invalid stream specifier: %s. \n " , spec );
return ret ;
2019-02-05 00:16:36 +01:00
}
2012-09-26 12:13:53 +02:00
int ff_generate_avci_extradata ( AVStream * st )
2012-09-26 12:13:53 +02:00
{
static const uint8_t avci100_1080p_extradata [] = {
// SPS
0x00 , 0x00 , 0x00 , 0x01 , 0x67 , 0x7a , 0x10 , 0x29 ,
0xb6 , 0xd4 , 0x20 , 0x22 , 0x33 , 0x19 , 0xc6 , 0x63 ,
0x23 , 0x21 , 0x01 , 0x11 , 0x98 , 0xce , 0x33 , 0x19 ,
0x18 , 0x21 , 0x02 , 0x56 , 0xb9 , 0x3d , 0x7d , 0x7e ,
0x4f , 0xe3 , 0x3f , 0x11 , 0xf1 , 0x9e , 0x08 , 0xb8 ,
0x8c , 0x54 , 0x43 , 0xc0 , 0x78 , 0x02 , 0x27 , 0xe2 ,
0x70 , 0x1e , 0x30 , 0x10 , 0x10 , 0x14 , 0x00 , 0x00 ,
0x03 , 0x00 , 0x04 , 0x00 , 0x00 , 0x03 , 0x00 , 0xca ,
0x10 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
// PPS
0x00 , 0x00 , 0x00 , 0x01 , 0x68 , 0xce , 0x33 , 0x48 ,
0xd0
};
static const uint8_t avci100_1080i_extradata [] = {
// SPS
0x00 , 0x00 , 0x00 , 0x01 , 0x67 , 0x7a , 0x10 , 0x29 ,
0xb6 , 0xd4 , 0x20 , 0x22 , 0x33 , 0x19 , 0xc6 , 0x63 ,
0x23 , 0x21 , 0x01 , 0x11 , 0x98 , 0xce , 0x33 , 0x19 ,
0x18 , 0x21 , 0x03 , 0x3a , 0x46 , 0x65 , 0x6a , 0x65 ,
0x24 , 0xad , 0xe9 , 0x12 , 0x32 , 0x14 , 0x1a , 0x26 ,
0x34 , 0xad , 0xa4 , 0x41 , 0x82 , 0x23 , 0x01 , 0x50 ,
0x2b , 0x1a , 0x24 , 0x69 , 0x48 , 0x30 , 0x40 , 0x2e ,
0x11 , 0x12 , 0x08 , 0xc6 , 0x8c , 0x04 , 0x41 , 0x28 ,
0x4c , 0x34 , 0xf0 , 0x1e , 0x01 , 0x13 , 0xf2 , 0xe0 ,
0x3c , 0x60 , 0x20 , 0x20 , 0x28 , 0x00 , 0x00 , 0x03 ,
2015-03-23 21:18:42 +01:00
0x00 , 0x08 , 0x00 , 0x00 , 0x03 , 0x01 , 0x94 , 0x20 ,
2012-09-26 12:13:53 +02:00
// PPS
0x00 , 0x00 , 0x00 , 0x01 , 0x68 , 0xce , 0x33 , 0x48 ,
0xd0
};
2014-10-29 13:04:48 +00:00
static const uint8_t avci50_1080p_extradata [] = {
// SPS
0x00 , 0x00 , 0x00 , 0x01 , 0x67 , 0x6e , 0x10 , 0x28 ,
0xa6 , 0xd4 , 0x20 , 0x32 , 0x33 , 0x0c , 0x71 , 0x18 ,
0x88 , 0x62 , 0x10 , 0x19 , 0x19 , 0x86 , 0x38 , 0x8c ,
0x44 , 0x30 , 0x21 , 0x02 , 0x56 , 0x4e , 0x6f , 0x37 ,
0xcd , 0xf9 , 0xbf , 0x81 , 0x6b , 0xf3 , 0x7c , 0xde ,
0x6e , 0x6c , 0xd3 , 0x3c , 0x05 , 0xa0 , 0x22 , 0x7e ,
0x5f , 0xfc , 0x00 , 0x0c , 0x00 , 0x13 , 0x8c , 0x04 ,
0x04 , 0x05 , 0x00 , 0x00 , 0x03 , 0x00 , 0x01 , 0x00 ,
0x00 , 0x03 , 0x00 , 0x32 , 0x84 , 0x00 , 0x00 , 0x00 ,
// PPS
0x00 , 0x00 , 0x00 , 0x01 , 0x68 , 0xee , 0x31 , 0x12 ,
0x11
};
2012-09-26 12:13:53 +02:00
static const uint8_t avci50_1080i_extradata [] = {
// SPS
0x00 , 0x00 , 0x00 , 0x01 , 0x67 , 0x6e , 0x10 , 0x28 ,
0xa6 , 0xd4 , 0x20 , 0x32 , 0x33 , 0x0c , 0x71 , 0x18 ,
0x88 , 0x62 , 0x10 , 0x19 , 0x19 , 0x86 , 0x38 , 0x8c ,
0x44 , 0x30 , 0x21 , 0x02 , 0x56 , 0x4e , 0x6e , 0x61 ,
0x87 , 0x3e , 0x73 , 0x4d , 0x98 , 0x0c , 0x03 , 0x06 ,
0x9c , 0x0b , 0x73 , 0xe6 , 0xc0 , 0xb5 , 0x18 , 0x63 ,
0x0d , 0x39 , 0xe0 , 0x5b , 0x02 , 0xd4 , 0xc6 , 0x19 ,
0x1a , 0x79 , 0x8c , 0x32 , 0x34 , 0x24 , 0xf0 , 0x16 ,
2013-01-05 09:20:03 +01:00
0x81 , 0x13 , 0xf7 , 0xff , 0x80 , 0x02 , 0x00 , 0x01 ,
0xf1 , 0x80 , 0x80 , 0x80 , 0xa0 , 0x00 , 0x00 , 0x03 ,
2012-09-26 12:13:53 +02:00
0x00 , 0x20 , 0x00 , 0x00 , 0x06 , 0x50 , 0x80 , 0x00 ,
// PPS
0x00 , 0x00 , 0x00 , 0x01 , 0x68 , 0xee , 0x31 , 0x12 ,
0x11
};
static const uint8_t avci100_720p_extradata [] = {
// SPS
0x00 , 0x00 , 0x00 , 0x01 , 0x67 , 0x7a , 0x10 , 0x29 ,
0xb6 , 0xd4 , 0x20 , 0x2a , 0x33 , 0x1d , 0xc7 , 0x62 ,
0xa1 , 0x08 , 0x40 , 0x54 , 0x66 , 0x3b , 0x8e , 0xc5 ,
0x42 , 0x02 , 0x10 , 0x25 , 0x64 , 0x2c , 0x89 , 0xe8 ,
0x85 , 0xe4 , 0x21 , 0x4b , 0x90 , 0x83 , 0x06 , 0x95 ,
0xd1 , 0x06 , 0x46 , 0x97 , 0x20 , 0xc8 , 0xd7 , 0x43 ,
0x08 , 0x11 , 0xc2 , 0x1e , 0x4c , 0x91 , 0x0f , 0x01 ,
0x40 , 0x16 , 0xec , 0x07 , 0x8c , 0x04 , 0x04 , 0x05 ,
0x00 , 0x00 , 0x03 , 0x00 , 0x01 , 0x00 , 0x00 , 0x03 ,
0x00 , 0x64 , 0x84 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
// PPS
0x00 , 0x00 , 0x00 , 0x01 , 0x68 , 0xce , 0x31 , 0x12 ,
0x11
};
2014-10-29 13:04:48 +00:00
static const uint8_t avci50_720p_extradata [] = {
// SPS
0x00 , 0x00 , 0x00 , 0x01 , 0x67 , 0x6e , 0x10 , 0x20 ,
0xa6 , 0xd4 , 0x20 , 0x32 , 0x33 , 0x0c , 0x71 , 0x18 ,
0x88 , 0x62 , 0x10 , 0x19 , 0x19 , 0x86 , 0x38 , 0x8c ,
0x44 , 0x30 , 0x21 , 0x02 , 0x56 , 0x4e , 0x6f , 0x37 ,
0xcd , 0xf9 , 0xbf , 0x81 , 0x6b , 0xf3 , 0x7c , 0xde ,
0x6e , 0x6c , 0xd3 , 0x3c , 0x0f , 0x01 , 0x6e , 0xff ,
0xc0 , 0x00 , 0xc0 , 0x01 , 0x38 , 0xc0 , 0x40 , 0x40 ,
0x50 , 0x00 , 0x00 , 0x03 , 0x00 , 0x10 , 0x00 , 0x00 ,
0x06 , 0x48 , 0x40 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
// PPS
0x00 , 0x00 , 0x00 , 0x01 , 0x68 , 0xee , 0x31 , 0x12 ,
0x11
};
2012-09-26 12:13:53 +02:00
const uint8_t * data = NULL ;
2019-12-10 22:59:53 +01:00
int ret , size = 0 ;
2012-09-26 12:13:53 +02:00
2014-06-18 20:42:52 +02:00
if ( st -> codecpar -> width == 1920 ) {
if ( st -> codecpar -> field_order == AV_FIELD_PROGRESSIVE ) {
2012-09-26 12:13:53 +02:00
data = avci100_1080p_extradata ;
size = sizeof ( avci100_1080p_extradata );
} else {
data = avci100_1080i_extradata ;
size = sizeof ( avci100_1080i_extradata );
}
2014-06-18 20:42:52 +02:00
} else if ( st -> codecpar -> width == 1440 ) {
2016-04-10 20:58:15 +01:00
if ( st -> codecpar -> field_order == AV_FIELD_PROGRESSIVE ) {
2014-10-29 13:04:48 +00:00
data = avci50_1080p_extradata ;
size = sizeof ( avci50_1080p_extradata );
} else {
data = avci50_1080i_extradata ;
size = sizeof ( avci50_1080i_extradata );
}
2014-06-18 20:42:52 +02:00
} else if ( st -> codecpar -> width == 1280 ) {
2012-09-26 12:13:53 +02:00
data = avci100_720p_extradata ;
size = sizeof ( avci100_720p_extradata );
2016-04-10 20:58:15 +01:00
} else if ( st -> codecpar -> width == 960 ) {
2014-10-29 13:04:48 +00:00
data = avci50_720p_extradata ;
size = sizeof ( avci50_720p_extradata );
2012-09-26 12:13:53 +02:00
}
2012-09-26 12:13:53 +02:00
2012-09-26 12:13:53 +02:00
if ( ! size )
2012-09-26 12:13:53 +02:00
return 0 ;
2019-12-10 22:59:53 +01:00
if (( ret = ff_alloc_extradata ( st -> codecpar , size )) < 0 )
return ret ;
2014-06-18 20:42:52 +02:00
memcpy ( st -> codecpar -> extradata , data , size );
2012-09-26 12:13:53 +02:00
return 0 ;
2012-09-26 12:13:53 +02:00
}
2014-05-19 16:29:30 +02:00
2016-06-27 11:28:12 +02:00
uint8_t * av_stream_get_side_data ( const AVStream * st ,
2021-04-14 14:59:32 +02:00
enum AVPacketSideDataType type , size_t * size )
2014-05-19 16:29:30 +02:00
{
int i ;
for ( i = 0 ; i < st -> nb_side_data ; i ++ ) {
if ( st -> side_data [ i ]. type == type ) {
if ( size )
* size = st -> side_data [ i ]. size ;
return st -> side_data [ i ]. data ;
}
}
2020-05-22 00:08:00 +02:00
if ( size )
* size = 0 ;
2014-05-19 16:29:30 +02:00
return NULL ;
}
2014-11-14 12:45:08 +01:00
2016-11-17 02:02:41 -03:00
int av_stream_add_side_data ( AVStream * st , enum AVPacketSideDataType type ,
uint8_t * data , size_t size )
2014-11-14 12:45:08 +01:00
{
AVPacketSideData * sd , * tmp ;
int i ;
for ( i = 0 ; i < st -> nb_side_data ; i ++ ) {
sd = & st -> side_data [ i ];
if ( sd -> type == type ) {
av_freep ( & sd -> data );
sd -> data = data ;
sd -> size = size ;
2016-11-17 02:02:41 -03:00
return 0 ;
2014-11-14 12:45:08 +01:00
}
}
2016-11-19 14:33:10 -03:00
if (( unsigned ) st -> nb_side_data + 1 >= INT_MAX / sizeof ( * st -> side_data ))
return AVERROR ( ERANGE );
2016-11-21 23:01:48 -03:00
tmp = av_realloc ( st -> side_data , ( st -> nb_side_data + 1 ) * sizeof ( * tmp ));
2014-11-14 12:45:08 +01:00
if ( ! tmp ) {
2016-11-17 02:02:41 -03:00
return AVERROR ( ENOMEM );
2014-11-14 12:45:08 +01:00
}
st -> side_data = tmp ;
st -> nb_side_data ++ ;
sd = & st -> side_data [ st -> nb_side_data - 1 ];
sd -> type = type ;
sd -> data = data ;
sd -> size = size ;
2016-11-17 02:02:41 -03:00
return 0 ;
}
uint8_t * av_stream_new_side_data ( AVStream * st , enum AVPacketSideDataType type ,
2021-04-14 14:59:32 +02:00
size_t size )
2016-11-17 02:02:41 -03:00
{
int ret ;
uint8_t * data = av_malloc ( size );
if ( ! data )
return NULL ;
ret = av_stream_add_side_data ( st , type , data , size );
if ( ret < 0 ) {
av_freep ( & data );
return NULL ;
}
2014-11-14 12:45:08 +01:00
return data ;
}
2015-10-07 21:23:11 -05:00
2015-10-07 21:10:08 -05:00
int ff_stream_add_bitstream_filter ( AVStream * st , const char * name , const char * args )
{
2016-04-20 01:15:35 -05:00
int ret ;
const AVBitStreamFilter * bsf ;
AVBSFContext * bsfc ;
2020-04-18 10:49:54 +02:00
av_assert0 ( ! st -> internal -> bsfc );
2015-10-07 21:10:08 -05:00
2016-04-20 01:15:35 -05:00
if ( ! ( bsf = av_bsf_get_by_name ( name ))) {
2015-10-07 21:10:08 -05:00
av_log ( NULL , AV_LOG_ERROR , "Unknown bitstream filter '%s' \n " , name );
2016-04-20 01:15:35 -05:00
return AVERROR_BSF_NOT_FOUND ;
2015-10-07 21:10:08 -05:00
}
2016-04-20 01:15:35 -05:00
if (( ret = av_bsf_alloc ( bsf , & bsfc )) < 0 )
return ret ;
2020-04-18 10:49:54 +02:00
bsfc -> time_base_in = st -> time_base ;
if (( ret = avcodec_parameters_copy ( bsfc -> par_in , st -> codecpar )) < 0 ) {
2016-04-20 01:15:35 -05:00
av_bsf_free ( & bsfc );
return ret ;
}
if ( args && bsfc -> filter -> priv_class ) {
const AVOption * opt = av_opt_next ( bsfc -> priv_data , NULL );
const char * shorthand [ 2 ] = { NULL };
if ( opt )
shorthand [ 0 ] = opt -> name ;
if (( ret = av_opt_set_from_string ( bsfc -> priv_data , args , shorthand , "=" , ":" )) < 0 ) {
av_bsf_free ( & bsfc );
return ret ;
}
}
if (( ret = av_bsf_init ( bsfc )) < 0 ) {
av_bsf_free ( & bsfc );
return ret ;
}
2020-04-18 10:49:54 +02:00
st -> internal -> bsfc = bsfc ;
2016-04-20 01:15:35 -05:00
2016-04-10 20:58:15 +01:00
av_log ( NULL , AV_LOG_VERBOSE ,
2015-10-07 21:10:08 -05:00
"Automatically inserted bitstream filter '%s'; args='%s' \n " ,
name , args ? args : "" );
return 1 ;
}
2016-07-04 16:45:13 +02:00
int ff_format_output_open ( AVFormatContext * s , const char * url , AVDictionary ** options )
{
if ( ! s -> oformat )
return AVERROR ( EINVAL );
if ( ! ( s -> oformat -> flags & AVFMT_NOFILE ))
return s -> io_open ( s , & s -> pb , url , AVIO_FLAG_WRITE , options );
return 0 ;
}
2016-01-16 17:53:43 +01:00
void ff_format_io_close ( AVFormatContext * s , AVIOContext ** pb )
{
if ( * pb )
s -> io_close ( s , * pb );
* pb = NULL ;
}
2016-02-04 03:28:19 +01:00
2017-12-29 18:11:09 +08:00
int ff_is_http_proto ( char * filename ) {
const char * proto = avio_find_protocol_name ( filename );
return proto ? ( ! av_strcasecmp ( proto , "http" ) || ! av_strcasecmp ( proto , "https" )) : 0 ;
}
2016-02-04 03:28:19 +01:00
int ff_parse_creation_time_metadata ( AVFormatContext * s , int64_t * timestamp , int return_seconds )
{
AVDictionaryEntry * entry ;
int64_t parsed_timestamp ;
int ret ;
if (( entry = av_dict_get ( s -> metadata , "creation_time" , NULL , 0 ))) {
if (( ret = av_parse_time ( & parsed_timestamp , entry -> value , 0 )) >= 0 ) {
* timestamp = return_seconds ? parsed_timestamp / 1000000 : parsed_timestamp ;
return 1 ;
} else {
av_log ( s , AV_LOG_WARNING , "Failed to parse creation_time %s \n " , entry -> value );
return ret ;
}
}
return 0 ;
}
2016-03-02 03:14:05 +01:00
2016-02-22 03:13:20 +01:00
int ff_standardize_creation_time ( AVFormatContext * s )
{
int64_t timestamp ;
int ret = ff_parse_creation_time_metadata ( s , & timestamp , 0 );
2016-06-29 22:44:59 +02:00
if ( ret == 1 )
return avpriv_dict_set_timestamp ( & s -> metadata , "creation_time" , timestamp );
2016-02-22 03:13:20 +01:00
return ret ;
}
2016-03-03 08:25:58 +01:00
int ff_get_packet_palette ( AVFormatContext * s , AVPacket * pkt , int ret , uint32_t * palette )
2016-03-02 03:14:05 +01:00
{
2016-03-03 08:25:58 +01:00
uint8_t * side_data ;
2021-04-14 14:59:32 +02:00
size_t size ;
2016-03-02 03:14:05 +01:00
2016-03-03 08:25:58 +01:00
side_data = av_packet_get_side_data ( pkt , AV_PKT_DATA_PALETTE , & size );
if ( side_data ) {
if ( size != AVPALETTE_SIZE ) {
av_log ( s , AV_LOG_ERROR , "Invalid palette side data \n " );
return AVERROR_INVALIDDATA ;
}
memcpy ( palette , side_data , AVPALETTE_SIZE );
return 1 ;
2016-03-02 03:14:05 +01:00
}
2016-03-03 08:25:58 +01:00
if ( ret == CONTAINS_PAL ) {
int i ;
for ( i = 0 ; i < AVPALETTE_COUNT ; i ++ )
palette [ i ] = AV_RL32 ( pkt -> data + pkt -> size - AVPALETTE_SIZE + i * 4 );
return 1 ;
}
2016-03-02 03:14:05 +01:00
return 0 ;
}
2016-03-31 21:49:02 +01:00
int ff_bprint_to_codecpar_extradata ( AVCodecParameters * par , struct AVBPrint * buf )
{
int ret ;
char * str ;
ret = av_bprint_finalize ( buf , & str );
if ( ret < 0 )
return ret ;
if ( ! av_bprint_is_complete ( buf )) {
av_free ( str );
return AVERROR ( ENOMEM );
}
par -> extradata = str ;
/* Note: the string is NUL terminated (so extradata can be read as a
* string), but the ending character is not accounted in the size (in
* binary formats you are likely not supposed to mux that character). When
* extradata is copied, it is also padded with AV_INPUT_BUFFER_PADDING_SIZE
* zeros. */
par -> extradata_size = buf -> len ;
return 0 ;
}
2016-09-09 16:38:21 +02:00
int avformat_transfer_internal_stream_timing_info ( const AVOutputFormat * ofmt ,
AVStream * ost , const AVStream * ist ,
enum AVTimebaseSource copy_tb )
{
//TODO: use [io]st->internal->avctx
2020-10-01 22:47:51 -03:00
const AVCodecContext * dec_ctx ;
AVCodecContext * enc_ctx ;
dec_ctx = ist -> internal -> avctx ;
enc_ctx = ost -> internal -> avctx ;
2016-09-09 16:38:21 +02:00
enc_ctx -> time_base = ist -> time_base ;
/*
* Avi is a special case here because it supports variable fps but
* having the fps and timebase differe significantly adds quite some
* overhead
*/
if ( ! strcmp ( ofmt -> name , "avi" )) {
#if FF_API_R_FRAME_RATE
if ( copy_tb == AVFMT_TBCF_AUTO && ist -> r_frame_rate . num
&& av_q2d ( ist -> r_frame_rate ) >= av_q2d ( ist -> avg_frame_rate )
&& 0.5 / av_q2d ( ist -> r_frame_rate ) > av_q2d ( ist -> time_base )
&& 0.5 / av_q2d ( ist -> r_frame_rate ) > av_q2d ( dec_ctx -> time_base )
&& av_q2d ( ist -> time_base ) < 1.0 / 500 && av_q2d ( dec_ctx -> time_base ) < 1.0 / 500
|| copy_tb == AVFMT_TBCF_R_FRAMERATE ) {
enc_ctx -> time_base . num = ist -> r_frame_rate . den ;
enc_ctx -> time_base . den = 2 * ist -> r_frame_rate . num ;
enc_ctx -> ticks_per_frame = 2 ;
} else
#endif
if ( copy_tb == AVFMT_TBCF_AUTO && av_q2d ( dec_ctx -> time_base ) * dec_ctx -> ticks_per_frame > 2 * av_q2d ( ist -> time_base )
&& av_q2d ( ist -> time_base ) < 1.0 / 500
|| copy_tb == AVFMT_TBCF_DECODER ) {
enc_ctx -> time_base = dec_ctx -> time_base ;
enc_ctx -> time_base . num *= dec_ctx -> ticks_per_frame ;
enc_ctx -> time_base . den *= 2 ;
enc_ctx -> ticks_per_frame = 2 ;
}
} else if ( ! ( ofmt -> flags & AVFMT_VARIABLE_FPS )
2016-09-14 10:00:08 +02:00
&& ! av_match_name ( ofmt -> name , "mov,mp4,3gp,3g2,psp,ipod,ismv,f4v" )) {
2016-09-09 16:38:21 +02:00
if ( copy_tb == AVFMT_TBCF_AUTO && dec_ctx -> time_base . den
&& av_q2d ( dec_ctx -> time_base ) * dec_ctx -> ticks_per_frame > av_q2d ( ist -> time_base )
&& av_q2d ( ist -> time_base ) < 1.0 / 500
|| copy_tb == AVFMT_TBCF_DECODER ) {
enc_ctx -> time_base = dec_ctx -> time_base ;
enc_ctx -> time_base . num *= dec_ctx -> ticks_per_frame ;
}
}
2016-09-01 16:48:45 +02:00
if (( enc_ctx -> codec_tag == AV_RL32 ( "tmcd" ) || ost -> codecpar -> codec_tag == AV_RL32 ( "tmcd" ))
2016-09-09 16:38:21 +02:00
&& dec_ctx -> time_base . num < dec_ctx -> time_base . den
&& dec_ctx -> time_base . num > 0
&& 121LL * dec_ctx -> time_base . num > dec_ctx -> time_base . den ) {
enc_ctx -> time_base = dec_ctx -> time_base ;
}
av_reduce ( & enc_ctx -> time_base . num , & enc_ctx -> time_base . den ,
enc_ctx -> time_base . num , enc_ctx -> time_base . den , INT_MAX );
return 0 ;
}
2016-09-27 10:07:14 -03:00
AVRational av_stream_get_codec_timebase ( const AVStream * st )
{
// See avformat_transfer_internal_stream_timing_info() TODO.
return st -> internal -> avctx -> time_base ;
}
2017-12-29 01:01:37 +01:00
void ff_format_set_url ( AVFormatContext * s , char * url )
{
av_assert0 ( url );
av_freep ( & s -> url );
s -> url = url ;
}