/*
- * various utility functions for use within FFmpeg
+ * various utility functions for use within Libav
* Copyright (c) 2000, 2001, 2002 Fabrice Bellard
*
- * This file is part of FFmpeg.
+ * This file is part of Libav.
*
- * FFmpeg is free software; you can redistribute it and/or
+ * Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * FFmpeg is distributed in the hope that it will be useful,
+ * Libav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+/* #define DEBUG */
+
#include "avformat.h"
+#include "avio_internal.h"
#include "internal.h"
#include "libavcodec/internal.h"
#include "libavutil/opt.h"
#include "libavutil/avstring.h"
#include "riff.h"
#include "audiointerleave.h"
+#include "url.h"
#include <sys/time.h>
#include <time.h>
#include <strings.h>
/**
* @file
- * various utility functions for use within FFmpeg
+ * various utility functions for use within Libav
*/
unsigned avformat_version(void)
const char *avformat_configuration(void)
{
- return FFMPEG_CONFIGURATION;
+ return LIBAV_CONFIGURATION;
}
const char *avformat_license(void)
{
#define LICENSE_PREFIX "libavformat license: "
- return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1;
+ return LICENSE_PREFIX LIBAV_LICENSE + sizeof(LICENSE_PREFIX) - 1;
}
/* fraction handling */
}
/** head of registered input format linked list */
-#if !FF_API_FIRST_FORMAT
-static
-#endif
-AVInputFormat *first_iformat = NULL;
+static AVInputFormat *first_iformat = NULL;
/** head of registered output format linked list */
-#if !FF_API_FIRST_FORMAT
-static
-#endif
-AVOutputFormat *first_oformat = NULL;
+static AVOutputFormat *first_oformat = NULL;
AVInputFormat *av_iformat_next(AVInputFormat *f)
{
return !strcasecmp(name, names);
}
-#if FF_API_GUESS_FORMAT
-AVOutputFormat *guess_format(const char *short_name, const char *filename,
- const char *mime_type)
-{
- return av_guess_format(short_name, filename, mime_type);
-}
-#endif
-
AVOutputFormat *av_guess_format(const char *short_name, const char *filename,
const char *mime_type)
{
#if CONFIG_IMAGE2_MUXER
if (!short_name && filename &&
av_filename_number_test(filename) &&
- av_guess_image2_codec(filename) != CODEC_ID_NONE) {
+ ff_guess_image2_codec(filename) != CODEC_ID_NONE) {
return av_guess_format("image2", NULL, NULL);
}
#endif
return fmt_found;
}
-#if FF_API_GUESS_FORMAT
-AVOutputFormat *guess_stream_format(const char *short_name, const char *filename,
- const char *mime_type)
-{
- AVOutputFormat *fmt = av_guess_format(short_name, filename, mime_type);
-
- if (fmt) {
- AVOutputFormat *stream_fmt;
- char stream_format_name[64];
-
- snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", fmt->name);
- stream_fmt = av_guess_format(stream_format_name, NULL, NULL);
-
- if (stream_fmt)
- fmt = stream_fmt;
- }
-
- return fmt;
-}
-#endif
-
enum CodecID av_guess_codec(AVOutputFormat *fmt, const char *short_name,
const char *filename, const char *mime_type, enum AVMediaType type){
if(type == AVMEDIA_TYPE_VIDEO){
#if CONFIG_IMAGE2_MUXER
if(!strcmp(fmt->name, "image2") || !strcmp(fmt->name, "image2pipe")){
- codec_id= av_guess_image2_codec(filename);
+ codec_id= ff_guess_image2_codec(filename);
}
#endif
if(codec_id == CODEC_ID_NONE)
return NULL;
}
-#if FF_API_SYMVER && CONFIG_SHARED && HAVE_SYMVER
-FF_SYMVER(void, av_destruct_packet_nofree, (AVPacket *pkt), "LIBAVFORMAT_52")
-{
- av_destruct_packet_nofree(pkt);
-}
-
-FF_SYMVER(void, av_destruct_packet, (AVPacket *pkt), "LIBAVFORMAT_52")
-{
- av_destruct_packet(pkt);
-}
-
-FF_SYMVER(int, av_new_packet, (AVPacket *pkt, int size), "LIBAVFORMAT_52")
-{
- return av_new_packet(pkt, size);
-}
-FF_SYMVER(int, av_dup_packet, (AVPacket *pkt), "LIBAVFORMAT_52")
-{
- return av_dup_packet(pkt);
-}
-
-FF_SYMVER(void, av_free_packet, (AVPacket *pkt), "LIBAVFORMAT_52")
-{
- av_free_packet(pkt);
-}
-
-FF_SYMVER(void, av_init_packet, (AVPacket *pkt), "LIBAVFORMAT_52")
-{
- av_log(NULL, AV_LOG_WARNING, "Diverting av_*_packet function calls to libavcodec. Recompile to improve performance\n");
- av_init_packet(pkt);
-}
-#endif
-
-int av_get_packet(ByteIOContext *s, AVPacket *pkt, int size)
+int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
{
int ret= av_new_packet(pkt, size);
if(ret<0)
return ret;
- pkt->pos= url_ftell(s);
+ pkt->pos= avio_tell(s);
- ret= get_buffer(s, pkt->data, size);
+ ret= avio_read(s, pkt->data, size);
if(ret<=0)
av_free_packet(pkt);
else
return ret;
}
-int av_append_packet(ByteIOContext *s, AVPacket *pkt, int size)
+int av_append_packet(AVIOContext *s, AVPacket *pkt, int size)
{
int ret;
int old_size;
ret = av_grow_packet(pkt, size);
if (ret < 0)
return ret;
- ret = get_buffer(s, pkt->data + old_size, size);
+ ret = avio_read(s, pkt->data + old_size, size);
av_shrink_packet(pkt, old_size + FFMAX(ret, 0));
return ret;
}
{
AVProbeData lpd = *pd;
AVInputFormat *fmt1 = NULL, *fmt;
- int score;
+ int score, id3 = 0;
if (lpd.buf_size > 10 && ff_id3v2_match(lpd.buf, ID3v2_DEFAULT_MAGIC)) {
int id3len = ff_id3v2_tag_len(lpd.buf);
lpd.buf += id3len;
lpd.buf_size -= id3len;
}
+ id3 = 1;
}
fmt = NULL;
}else if (score == *score_max)
fmt = NULL;
}
+
+ /* a hack for files with huge id3v2 tags -- try to guess by file extension. */
+ if (!fmt && id3 && *score_max < AVPROBE_SCORE_MAX/4) {
+ while ((fmt = av_iformat_next(fmt)))
+ if (fmt->extensions && av_match_ext(lpd.filename, fmt->extensions)) {
+ *score_max = AVPROBE_SCORE_MAX/4;
+ break;
+ }
+ }
+
return fmt;
}
* Open a media file from an IO stream. 'fmt' must be specified.
*/
int av_open_input_stream(AVFormatContext **ic_ptr,
- ByteIOContext *pb, const char *filename,
+ AVIOContext *pb, const char *filename,
AVInputFormat *fmt, AVFormatParameters *ap)
{
int err;
ic->priv_data = NULL;
}
- // e.g. AVFMT_NOFILE formats will not have a ByteIOContext
+ // e.g. AVFMT_NOFILE formats will not have a AVIOContext
if (ic->pb)
ff_id3v2_read(ic, ID3v2_DEFAULT_MAGIC);
}
if (pb && !ic->data_offset)
- ic->data_offset = url_ftell(ic->pb);
-
-#if FF_API_OLD_METADATA
- ff_metadata_demux_compat(ic);
-#endif
+ ic->data_offset = avio_tell(ic->pb);
ic->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE;
#define PROBE_BUF_MIN 2048
#define PROBE_BUF_MAX (1<<20)
-int ff_probe_input_buffer(ByteIOContext *pb, AVInputFormat **fmt,
+int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt,
const char *filename, void *logctx,
unsigned int offset, unsigned int max_probe_size)
{
/* read probe data */
buf = av_realloc(buf, probe_size + AVPROBE_PADDING_SIZE);
- if ((ret = get_buffer(pb, buf + buf_offset, probe_size - buf_offset)) < 0) {
+ if ((ret = avio_read(pb, buf + buf_offset, probe_size - buf_offset)) < 0) {
/* fail if error was not end of file, otherwise, lower score */
if (ret != AVERROR_EOF) {
av_free(buf);
}
/* rewind. reuse probe buffer to avoid seeking */
- if ((ret = ff_rewind_with_probe_data(pb, buf, pd.buf_size)) < 0)
+ if ((ret = ffio_rewind_with_probe_data(pb, buf, pd.buf_size)) < 0)
av_free(buf);
return ret;
{
int err;
AVProbeData probe_data, *pd = &probe_data;
- ByteIOContext *pb = NULL;
+ AVIOContext *pb = NULL;
void *logctx= ap && ap->prealloced_context ? *ic_ptr : NULL;
pd->filename = "";
hack needed to handle RTSP/TCP */
if (!fmt || !(fmt->flags & AVFMT_NOFILE)) {
/* if no file needed do not try to open one */
- if ((err=url_fopen(&pb, filename, URL_RDONLY)) < 0) {
+ if ((err=avio_open(&pb, filename, AVIO_FLAG_READ)) < 0) {
goto fail;
}
if (buf_size > 0) {
- url_setbufsize(pb, buf_size);
+ ffio_set_buf_size(pb, buf_size);
}
- if (!fmt && (err = ff_probe_input_buffer(pb, &fmt, filename, logctx, 0, logctx ? (*ic_ptr)->probesize : 0)) < 0) {
+ if (!fmt && (err = av_probe_input_buffer(pb, &fmt, filename, logctx, 0, logctx ? (*ic_ptr)->probesize : 0)) < 0) {
goto fail;
}
}
/* check filename in case an image number is expected */
if (fmt->flags & AVFMT_NEEDNUMBER) {
if (!av_filename_number_test(filename)) {
- err = AVERROR_NUMEXPECTED;
+ err = AVERROR(EINVAL);
goto fail;
}
}
fail:
av_freep(&pd->buf);
if (pb)
- url_fclose(pb);
+ avio_close(pb);
if (ap && ap->prealloced_context)
av_free(*ic_ptr);
*ic_ptr = NULL;
if((s->flags & AVFMT_FLAG_IGNDTS) && pkt->pts != AV_NOPTS_VALUE)
pkt->dts= AV_NOPTS_VALUE;
- if (st->codec->codec_id != CODEC_ID_H264 && pc && pc->pict_type == FF_B_TYPE)
+ if (st->codec->codec_id != CODEC_ID_H264 && pc && pc->pict_type == AV_PICTURE_TYPE_B)
//FIXME Set low_delay = 0 when has_b_frames = 1
st->codec->has_b_frames = 1;
/* do we have a video B-frame ? */
delay= st->codec->has_b_frames;
presentation_delayed = 0;
+
+ // ignore delay caused by frame threading so that the mpeg2-without-dts
+ // warning will not trigger
+ if (delay && st->codec->active_thread_type&FF_THREAD_FRAME)
+ delay -= st->codec->thread_count-1;
+
/* XXX: need has_b_frame, but cannot get it if the codec is
not initialized */
if (delay &&
- pc && pc->pict_type != FF_B_TYPE)
+ pc && pc->pict_type != AV_PICTURE_TYPE_B)
presentation_delayed = 1;
if(pkt->pts != AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE && pkt->dts > pkt->pts && st->pts_wrap_bits<63
/* keyframe computation */
if (pc->key_frame == 1)
pkt->flags |= AV_PKT_FLAG_KEY;
- else if (pc->key_frame == -1 && pc->pict_type == FF_I_TYPE)
+ else if (pc->key_frame == -1 && pc->pict_type == AV_PICTURE_TYPE_I)
pkt->flags |= AV_PKT_FLAG_KEY;
}
if (pc)
return -1;
/* do the seek */
- if ((ret = url_fseek(s->pb, pos, SEEK_SET)) < 0)
+ if ((ret = avio_seek(s->pb, pos, SEEK_SET)) < 0)
return ret;
av_update_cur_dts(s, st, ts);
if(ts_max == AV_NOPTS_VALUE){
int step= 1024;
- filesize = url_fsize(s->pb);
+ filesize = avio_size(s->pb);
pos_max = filesize - 1;
do{
pos_max -= step;
#endif
pos_min = s->data_offset;
- pos_max = url_fsize(s->pb) - 1;
+ pos_max = avio_size(s->pb) - 1;
if (pos < pos_min) pos= pos_min;
else if(pos > pos_max) pos= pos_max;
- url_fseek(s->pb, pos, SEEK_SET);
+ avio_seek(s->pb, pos, SEEK_SET);
#if 0
av_update_cur_dts(s, st, ts);
if(st->nb_index_entries){
assert(st->index_entries);
ie= &st->index_entries[st->nb_index_entries-1];
- if ((ret = url_fseek(s->pb, ie->pos, SEEK_SET)) < 0)
+ if ((ret = avio_seek(s->pb, ie->pos, SEEK_SET)) < 0)
return ret;
av_update_cur_dts(s, st, ie->timestamp);
}else{
- if ((ret = url_fseek(s->pb, s->data_offset, SEEK_SET)) < 0)
+ if ((ret = avio_seek(s->pb, s->data_offset, SEEK_SET)) < 0)
return ret;
}
for(i=0;; i++) {
return 0;
}
ie = &st->index_entries[index];
- if ((ret = url_fseek(s->pb, ie->pos, SEEK_SET)) < 0)
+ if ((ret = avio_seek(s->pb, ie->pos, SEEK_SET)) < 0)
return ret;
av_update_cur_dts(s, st, ie->timestamp);
if (offset < 0)
offset = 0;
- url_fseek(ic->pb, offset, SEEK_SET);
+ avio_seek(ic->pb, offset, SEEK_SET);
read_size = 0;
for(;;) {
if (read_size >= DURATION_MAX_READ_SIZE<<(FFMAX(retry-1,0)))
fill_all_stream_timings(ic);
- url_fseek(ic->pb, old_offset, SEEK_SET);
+ avio_seek(ic->pb, old_offset, SEEK_SET);
for (i=0; i<ic->nb_streams; i++) {
st= ic->streams[i];
st->cur_dts= st->first_dts;
if (ic->iformat->flags & AVFMT_NOFILE) {
file_size = 0;
} else {
- file_size = url_fsize(ic->pb);
+ file_size = avio_size(ic->pb);
if (file_size < 0)
file_size = 0;
}
if ((!strcmp(ic->iformat->name, "mpeg") ||
!strcmp(ic->iformat->name, "mpegts")) &&
- file_size && !url_is_streamed(ic->pb)) {
+ file_size && ic->pb->seekable) {
/* get accurate estimate from the PTSes */
av_estimate_timings_from_pts(ic, old_offset);
} else if (av_has_duration(ic)) {
}
av_update_stream_timings(ic);
-#if 0
{
int i;
AVStream *st;
for(i = 0;i < ic->nb_streams; i++) {
st = ic->streams[i];
- printf("%d: start_time: %0.3f duration: %0.3f\n",
- i, (double)st->start_time / AV_TIME_BASE,
- (double)st->duration / AV_TIME_BASE);
+ av_dlog(ic, "%d: start_time: %0.3f duration: %0.3f\n", i,
+ (double) st->start_time / AV_TIME_BASE,
+ (double) st->duration / AV_TIME_BASE);
}
- printf("stream: start_time: %0.3f duration: %0.3f bitrate=%d kb/s\n",
- (double)ic->start_time / AV_TIME_BASE,
- (double)ic->duration / AV_TIME_BASE,
- ic->bit_rate / 1000);
+ av_dlog(ic, "stream: start_time: %0.3f duration: %0.3f bitrate=%d kb/s\n",
+ (double) ic->start_time / AV_TIME_BASE,
+ (double) ic->duration / AV_TIME_BASE,
+ ic->bit_rate / 1000);
}
-#endif
}
static int has_codec_parameters(AVCodecContext *enc)
static void compute_chapters_end(AVFormatContext *s)
{
- unsigned int i;
+ unsigned int i, j;
+ int64_t max_time = s->duration + (s->start_time == AV_NOPTS_VALUE) ? 0 : s->start_time;
- for (i=0; i+1<s->nb_chapters; i++)
+ for (i = 0; i < s->nb_chapters; i++)
if (s->chapters[i]->end == AV_NOPTS_VALUE) {
- assert(s->chapters[i]->start <= s->chapters[i+1]->start);
- assert(!av_cmp_q(s->chapters[i]->time_base, s->chapters[i+1]->time_base));
- s->chapters[i]->end = s->chapters[i+1]->start;
+ AVChapter *ch = s->chapters[i];
+ int64_t end = max_time ? av_rescale_q(max_time, AV_TIME_BASE_Q, ch->time_base)
+ : INT64_MAX;
+
+ for (j = 0; j < s->nb_chapters; j++) {
+ AVChapter *ch1 = s->chapters[j];
+ int64_t next_start = av_rescale_q(ch1->start, ch1->time_base, ch->time_base);
+ if (j != i && next_start > ch->start && next_start < end)
+ end = next_start;
+ }
+ ch->end = (end == INT64_MAX) ? ch->start : end;
}
-
- if (s->nb_chapters && s->chapters[i]->end == AV_NOPTS_VALUE) {
- assert(s->start_time != AV_NOPTS_VALUE);
- assert(s->duration > 0);
- s->chapters[i]->end = av_rescale_q(s->start_time + s->duration,
- AV_TIME_BASE_Q,
- s->chapters[i]->time_base);
- }
}
static int get_std_framerate(int i){
int i, count, ret, read_size, j;
AVStream *st;
AVPacket pkt1, *pkt;
- int64_t old_offset = url_ftell(ic->pb);
+ int64_t old_offset = avio_tell(ic->pb);
for(i=0;i<ic->nb_streams;i++) {
AVCodec *codec;
read_size = 0;
for(;;) {
if(url_interrupt_cb()){
- ret= AVERROR(EINTR);
+ ret= AVERROR_EXIT;
av_log(ic, AV_LOG_DEBUG, "interrupted\n");
break;
}
/* check if one codec still needs to be handled */
for(i=0;i<ic->nb_streams;i++) {
+ int fps_analyze_framecount = 20;
+
st = ic->streams[i];
if (!has_codec_parameters(st->codec))
break;
+ /* 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 */
+ if (av_q2d(st->time_base) > 0.0005)
+ fps_analyze_framecount *= 2;
/* variable fps and no guess at the real fps */
if( tb_unreliable(st->codec) && !(st->r_frame_rate.num && st->avg_frame_rate.num)
- && st->info->duration_count<20 && st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+ && st->info->duration_count < fps_analyze_framecount
+ && st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
break;
if(st->parser && st->parser->parser->split && !st->codec->extradata)
break;
}else if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
if(!st->codec->bits_per_coded_sample)
st->codec->bits_per_coded_sample= av_get_bits_per_sample(st->codec->codec_id);
+ // set stream disposition based on audio service type
+ switch (st->codec->audio_service_type) {
+ case AV_AUDIO_SERVICE_TYPE_EFFECTS:
+ st->disposition = AV_DISPOSITION_CLEAN_EFFECTS; break;
+ case AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED:
+ st->disposition = AV_DISPOSITION_VISUAL_IMPAIRED; break;
+ case AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED:
+ st->disposition = AV_DISPOSITION_HEARING_IMPAIRED; break;
+ case AV_AUDIO_SERVICE_TYPE_COMMENTARY:
+ st->disposition = AV_DISPOSITION_COMMENT; break;
+ case AV_AUDIO_SERVICE_TYPE_KARAOKE:
+ st->disposition = AV_DISPOSITION_KARAOKE; break;
+ }
}
}
continue;
if (wanted_stream_nb >= 0 && stream_number++ != wanted_stream_nb)
continue;
+ if (st->disposition & (AV_DISPOSITION_HEARING_IMPAIRED|AV_DISPOSITION_VISUAL_IMPAIRED))
+ continue;
if (decoder_ret) {
decoder = avcodec_find_decoder(ic->streams[i]->codec->codec_id);
if (!decoder) {
if (best_count >= st->codec_info_nb_frames)
continue;
best_count = st->codec_info_nb_frames;
- ret = i;
+ ret = program ? program[i] : i;
best_decoder = decoder;
if (program && i == nb_streams - 1 && ret < 0) {
program = NULL;
if (s->iformat->read_play)
return s->iformat->read_play(s);
if (s->pb)
- return av_url_read_fpause(s->pb, 0);
+ return avio_pause(s->pb, 0);
return AVERROR(ENOSYS);
}
if (s->iformat->read_pause)
return s->iformat->read_pause(s);
if (s->pb)
- return av_url_read_fpause(s->pb, 1);
+ return avio_pause(s->pb, 1);
return AVERROR(ENOSYS);
}
av_free(st->codec->extradata);
av_free(st->codec->subtitle_header);
av_free(st->codec);
-#if FF_API_OLD_METADATA
- av_free(st->filename);
-#endif
av_free(st->priv_data);
av_free(st->info);
av_free(st);
}
for(i=s->nb_programs-1; i>=0; i--) {
-#if FF_API_OLD_METADATA
- av_freep(&s->programs[i]->provider_name);
- av_freep(&s->programs[i]->name);
-#endif
av_metadata_free(&s->programs[i]->metadata);
av_freep(&s->programs[i]->stream_index);
av_freep(&s->programs[i]);
av_freep(&s->programs);
av_freep(&s->priv_data);
while(s->nb_chapters--) {
-#if FF_API_OLD_METADATA
- av_free(s->chapters[s->nb_chapters]->title);
-#endif
av_metadata_free(&s->chapters[s->nb_chapters]->metadata);
av_free(s->chapters[s->nb_chapters]);
}
av_freep(&s->chapters);
av_metadata_free(&s->metadata);
av_freep(&s->key);
+ av_freep(&s->streams);
av_free(s);
}
void av_close_input_file(AVFormatContext *s)
{
- ByteIOContext *pb = s->iformat->flags & AVFMT_NOFILE ? NULL : s->pb;
+ AVIOContext *pb = s->iformat->flags & AVFMT_NOFILE ? NULL : s->pb;
av_close_input_stream(s);
if (pb)
- url_fclose(pb);
+ avio_close(pb);
}
AVStream *av_new_stream(AVFormatContext *s, int id)
{
AVStream *st;
int i;
-
-#if FF_API_MAX_STREAMS
- if (s->nb_streams >= MAX_STREAMS){
- av_log(s, AV_LOG_ERROR, "Too many streams\n");
- return NULL;
- }
-#else
AVStream **streams;
if (s->nb_streams >= INT_MAX/sizeof(*streams))
if (!streams)
return NULL;
s->streams = streams;
-#endif
st = av_mallocz(sizeof(AVStream));
if (!st)
return NULL;
dynarray_add(&s->chapters, &s->nb_chapters, chapter);
}
-#if FF_API_OLD_METADATA
- av_free(chapter->title);
-#endif
av_metadata_set2(&chapter->metadata, "title", title, 0);
chapter->id = id;
chapter->time_base= time_base;
return AVERROR(ENOMEM);
}
-#if FF_API_OLD_METADATA
- ff_metadata_mux_compat(s);
-#endif
-
/* set muxer identification string */
if (s->nb_streams && !(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) {
av_metadata_set2(&s->metadata, "encoder", LIBAVFORMAT_IDENT, 0);
int delay = FFMAX(st->codec->has_b_frames, !!st->codec->max_b_frames);
int num, den, frame_size, i;
-// av_log(s, AV_LOG_DEBUG, "av_write_frame: pts:%"PRId64" dts:%"PRId64" cur_dts:%"PRId64" b:%d size:%d st:%d\n", pkt->pts, pkt->dts, st->cur_dts, delay, pkt->size, pkt->stream_index);
+ av_dlog(s, "av_write_frame: pts:%"PRId64" dts:%"PRId64" cur_dts:%"PRId64" b:%d size:%d st:%d\n",
+ pkt->pts, pkt->dts, st->cur_dts, delay, pkt->size, pkt->stream_index);
/* if(pkt->pts == AV_NOPTS_VALUE && pkt->dts == AV_NOPTS_VALUE)
return -1;*/
return ret;
ret= s->oformat->write_packet(s, pkt);
- if(!ret)
- ret= url_ferror(s->pb);
return ret;
}
AVStream *st2= s->streams[ next->stream_index];
int64_t a= st2->time_base.num * (int64_t)st ->time_base.den;
int64_t b= st ->time_base.num * (int64_t)st2->time_base.den;
- return av_rescale_rnd(pkt->dts, b, a, AV_ROUND_DOWN) < next->dts;
+ int64_t dts1 = av_rescale_rnd(pkt->dts, b, a, AV_ROUND_DOWN);
+ if (dts1 == next->dts)
+ return pkt->stream_index < next->stream_index;
+ return dts1 < next->dts;
}
int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush){
int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){
AVStream *st= s->streams[ pkt->stream_index];
+ int ret;
//FIXME/XXX/HACK drop zero sized packets
if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO && pkt->size==0)
return 0;
-//av_log(NULL, AV_LOG_DEBUG, "av_interleaved_write_frame %d %"PRId64" %"PRId64"\n", pkt->size, pkt->dts, pkt->pts);
- if(compute_pkt_fields2(s, st, pkt) < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
- return -1;
+ av_dlog(s, "av_interleaved_write_frame size:%d dts:%"PRId64" pts:%"PRId64"\n",
+ pkt->size, pkt->dts, pkt->pts);
+ if((ret = compute_pkt_fields2(s, st, pkt)) < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
+ return ret;
if(pkt->dts == AV_NOPTS_VALUE && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
- return -1;
+ return AVERROR(EINVAL);
for(;;){
AVPacket opkt;
if(ret<0)
return ret;
- if(url_ferror(s->pb))
- return url_ferror(s->pb);
}
}
if(ret<0)
goto fail;
- if(url_ferror(s->pb))
- goto fail;
}
if(s->oformat->write_trailer)
ret = s->oformat->write_trailer(s);
fail:
- if(ret == 0)
- ret=url_ferror(s->pb);
for(i=0;i<s->nb_streams;i++) {
av_freep(&s->streams[i]->priv_data);
av_freep(&s->streams[i]->index_entries);
if(st->codec->time_base.den && st->codec->time_base.num)
print_fps(1/av_q2d(st->codec->time_base), "tbc");
}
+ if (st->disposition & AV_DISPOSITION_DEFAULT)
+ av_log(NULL, AV_LOG_INFO, " (default)");
+ if (st->disposition & AV_DISPOSITION_DUB)
+ av_log(NULL, AV_LOG_INFO, " (dub)");
+ if (st->disposition & AV_DISPOSITION_ORIGINAL)
+ av_log(NULL, AV_LOG_INFO, " (original)");
+ if (st->disposition & AV_DISPOSITION_COMMENT)
+ av_log(NULL, AV_LOG_INFO, " (comment)");
+ if (st->disposition & AV_DISPOSITION_LYRICS)
+ av_log(NULL, AV_LOG_INFO, " (lyrics)");
+ if (st->disposition & AV_DISPOSITION_KARAOKE)
+ av_log(NULL, AV_LOG_INFO, " (karaoke)");
+ if (st->disposition & AV_DISPOSITION_FORCED)
+ av_log(NULL, AV_LOG_INFO, " (forced)");
+ if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
+ av_log(NULL, AV_LOG_INFO, " (hearing impaired)");
+ if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
+ av_log(NULL, AV_LOG_INFO, " (visual impaired)");
+ if (st->disposition & AV_DISPOSITION_CLEAN_EFFECTS)
+ av_log(NULL, AV_LOG_INFO, " (clean effects)");
av_log(NULL, AV_LOG_INFO, "\n");
dump_metadata(NULL, st->metadata, " ");
}
+#if FF_API_DUMP_FORMAT
void dump_format(AVFormatContext *ic,
int index,
const char *url,
int is_output)
+{
+ av_dump_format(ic, index, url, is_output);
+}
+#endif
+
+void av_dump_format(AVFormatContext *ic,
+ int index,
+ const char *url,
+ int is_output)
{
int i;
uint8_t *printed = av_mallocz(ic->nb_streams);
av_free(printed);
}
-#if FF_API_PARSE_FRAME_PARAM
-#include "libavcore/parseutils.h"
-
-int parse_image_size(int *width_ptr, int *height_ptr, const char *str)
-{
- return av_parse_video_size(width_ptr, height_ptr, str);
-}
-
-int parse_frame_rate(int *frame_rate_num, int *frame_rate_den, const char *arg)
-{
- AVRational frame_rate;
- int ret = av_parse_video_rate(&frame_rate, arg);
- *frame_rate_num= frame_rate.num;
- *frame_rate_den= frame_rate.den;
- return ret;
-}
-#endif
-
int64_t av_gettime(void)
{
struct timeval tv;
return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US;
}
-int64_t parse_date(const char *datestr, int duration)
-{
- const char *p;
- int64_t t;
- struct tm dt;
- int i;
- static const char * const date_fmt[] = {
- "%Y-%m-%d",
- "%Y%m%d",
- };
- static const char * const time_fmt[] = {
- "%H:%M:%S",
- "%H%M%S",
- };
- const char *q;
- int is_utc, len;
- char lastch;
- int negative = 0;
-
-#undef time
- time_t now = time(0);
-
- len = strlen(datestr);
- if (len > 0)
- lastch = datestr[len - 1];
- else
- lastch = '\0';
- is_utc = (lastch == 'z' || lastch == 'Z');
-
- memset(&dt, 0, sizeof(dt));
-
- p = datestr;
- q = NULL;
- if (!duration) {
- if (!strncasecmp(datestr, "now", len))
- return (int64_t) now * 1000000;
+#if FF_API_PARSE_DATE
+#include "libavutil/parseutils.h"
- /* parse the year-month-day part */
- for (i = 0; i < FF_ARRAY_ELEMS(date_fmt); i++) {
- q = small_strptime(p, date_fmt[i], &dt);
- if (q) {
- break;
- }
- }
-
- /* if the year-month-day part is missing, then take the
- * current year-month-day time */
- if (!q) {
- if (is_utc) {
- dt = *gmtime(&now);
- } else {
- dt = *localtime(&now);
- }
- dt.tm_hour = dt.tm_min = dt.tm_sec = 0;
- } else {
- p = q;
- }
-
- if (*p == 'T' || *p == 't' || *p == ' ')
- p++;
-
- /* parse the hour-minute-second part */
- for (i = 0; i < FF_ARRAY_ELEMS(time_fmt); i++) {
- q = small_strptime(p, time_fmt[i], &dt);
- if (q) {
- break;
- }
- }
- } else {
- /* parse datestr as a duration */
- if (p[0] == '-') {
- negative = 1;
- ++p;
- }
- /* parse datestr as HH:MM:SS */
- q = small_strptime(p, time_fmt[0], &dt);
- if (!q) {
- /* parse datestr as S+ */
- dt.tm_sec = strtol(p, (char **)&q, 10);
- if (q == p)
- /* the parsing didn't succeed */
- return INT64_MIN;
- dt.tm_min = 0;
- dt.tm_hour = 0;
- }
- }
-
- /* Now we have all the fields that we can get */
- if (!q) {
- return INT64_MIN;
- }
-
- if (duration) {
- t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec;
- } else {
- dt.tm_isdst = -1; /* unknown */
- if (is_utc) {
- t = mktimegm(&dt);
- } else {
- t = mktime(&dt);
- }
- }
-
- t *= 1000000;
-
- /* parse the .m... part */
- if (*q == '.') {
- int val, n;
- q++;
- for (val = 0, n = 100000; n >= 1; n /= 10, q++) {
- if (!isdigit(*q))
- break;
- val += n * (*q - '0');
- }
- t += val;
- }
- return negative ? -t : t;
+int64_t parse_date(const char *timestr, int duration)
+{
+ int64_t timeval;
+ av_parse_time(&timeval, timestr, duration);
+ return timeval;
}
+#endif
+
+#if FF_API_FIND_INFO_TAG
+#include "libavutil/parseutils.h"
int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
{
- const char *p;
- char tag[128], *q;
-
- p = info;
- if (*p == '?')
- p++;
- for(;;) {
- q = tag;
- while (*p != '\0' && *p != '=' && *p != '&') {
- if ((q - tag) < sizeof(tag) - 1)
- *q++ = *p;
- p++;
- }
- *q = '\0';
- q = arg;
- if (*p == '=') {
- p++;
- while (*p != '&' && *p != '\0') {
- if ((q - arg) < arg_size - 1) {
- if (*p == '+')
- *q++ = ' ';
- else
- *q++ = *p;
- }
- p++;
- }
- }
- *q = '\0';
- if (!strcmp(tag, tag1))
- return 1;
- if (*p != '&')
- break;
- p++;
- }
- return 0;
+ return av_find_info_tag(arg, arg_size, tag1, info);
}
+#endif
int av_get_frame_filename(char *buf, int buf_size,
const char *path, int number)
hex_dump_internal(avcl, NULL, level, buf, size);
}
- //FIXME needs to know the time_base
-static void pkt_dump_internal(void *avcl, FILE *f, int level, AVPacket *pkt, int dump_payload)
+static void pkt_dump_internal(void *avcl, FILE *f, int level, AVPacket *pkt, int dump_payload, AVRational time_base)
{
#undef fprintf
#define PRINT(...) do { if (!f) av_log(avcl, level, __VA_ARGS__); else fprintf(f, __VA_ARGS__); } while(0)
PRINT("stream #%d:\n", pkt->stream_index);
PRINT(" keyframe=%d\n", ((pkt->flags & AV_PKT_FLAG_KEY) != 0));
- PRINT(" duration=%0.3f\n", (double)pkt->duration / AV_TIME_BASE);
+ PRINT(" duration=%0.3f\n", pkt->duration * av_q2d(time_base));
/* DTS is _always_ valid after av_read_frame() */
PRINT(" dts=");
if (pkt->dts == AV_NOPTS_VALUE)
PRINT("N/A");
else
- PRINT("%0.3f", (double)pkt->dts / AV_TIME_BASE);
+ PRINT("%0.3f", pkt->dts * av_q2d(time_base));
/* PTS may not be known if B-frames are present. */
PRINT(" pts=");
if (pkt->pts == AV_NOPTS_VALUE)
PRINT("N/A");
else
- PRINT("%0.3f", (double)pkt->pts / AV_TIME_BASE);
+ PRINT("%0.3f", pkt->pts * av_q2d(time_base));
PRINT("\n");
PRINT(" size=%d\n", pkt->size);
#undef PRINT
av_hex_dump(f, pkt->data, pkt->size);
}
+#if FF_API_PKT_DUMP
void av_pkt_dump(FILE *f, AVPacket *pkt, int dump_payload)
{
- pkt_dump_internal(NULL, f, 0, pkt, dump_payload);
+ AVRational tb = { 1, AV_TIME_BASE };
+ pkt_dump_internal(NULL, f, 0, pkt, dump_payload, tb);
}
+#endif
-void av_pkt_dump_log(void *avcl, int level, AVPacket *pkt, int dump_payload)
+void av_pkt_dump2(FILE *f, AVPacket *pkt, int dump_payload, AVStream *st)
{
- pkt_dump_internal(avcl, NULL, level, pkt, dump_payload);
+ pkt_dump_internal(NULL, f, 0, pkt, dump_payload, st->time_base);
}
-#if FF_API_URL_SPLIT
-attribute_deprecated
-void ff_url_split(char *proto, int proto_size,
- char *authorization, int authorization_size,
- char *hostname, int hostname_size,
- int *port_ptr,
- char *path, int path_size,
- const char *url)
+#if FF_API_PKT_DUMP
+void av_pkt_dump_log(void *avcl, int level, AVPacket *pkt, int dump_payload)
{
- av_url_split(proto, proto_size,
- authorization, authorization_size,
- hostname, hostname_size,
- port_ptr,
- path, path_size,
- url);
+ AVRational tb = { 1, AV_TIME_BASE };
+ pkt_dump_internal(avcl, NULL, level, pkt, dump_payload, tb);
}
#endif
+void av_pkt_dump_log2(void *avcl, int level, AVPacket *pkt, int dump_payload,
+ AVStream *st)
+{
+ pkt_dump_internal(avcl, NULL, level, pkt, dump_payload, st->time_base);
+}
+
void av_url_split(char *proto, int proto_size,
char *authorization, int authorization_size,
char *hostname, int hostname_size,
}
return -1;
}
+
+void ff_make_absolute_url(char *buf, int size, const char *base,
+ const char *rel)
+{
+ char *sep;
+ /* Absolute path, relative to the current server */
+ if (base && strstr(base, "://") && rel[0] == '/') {
+ if (base != buf)
+ av_strlcpy(buf, base, size);
+ sep = strstr(buf, "://");
+ if (sep) {
+ sep += 3;
+ sep = strchr(sep, '/');
+ if (sep)
+ *sep = '\0';
+ }
+ av_strlcat(buf, rel, size);
+ return;
+ }
+ /* If rel actually is an absolute url, just copy it */
+ if (!base || strstr(rel, "://") || rel[0] == '/') {
+ av_strlcpy(buf, rel, size);
+ return;
+ }
+ if (base != buf)
+ av_strlcpy(buf, base, size);
+ /* Remove the file name from the base url */
+ sep = strrchr(buf, '/');
+ if (sep)
+ sep[1] = '\0';
+ else
+ buf[0] = '\0';
+ while (av_strstart(rel, "../", NULL) && sep) {
+ /* Remove the path delimiter at the end */
+ sep[0] = '\0';
+ sep = strrchr(buf, '/');
+ /* If the next directory name to pop off is "..", break here */
+ if (!strcmp(sep ? &sep[1] : buf, "..")) {
+ /* Readd the slash we just removed */
+ av_strlcat(buf, "/", size);
+ break;
+ }
+ /* Cut off the directory name */
+ if (sep)
+ sep[1] = '\0';
+ else
+ buf[0] = '\0';
+ rel += 3;
+ }
+ av_strlcat(buf, rel, size);
+}