/*
- * 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 "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 */
#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
#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)
{
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;
}
hack needed to handle RTSP/TCP */
if (!fmt || !(fmt->flags & AVFMT_NOFILE)) {
/* if no file needed do not try to open one */
- if ((err=avio_open(&pb, filename, URL_RDONLY)) < 0) {
+ if ((err=avio_open(&pb, filename, AVIO_RDONLY)) < 0) {
goto fail;
}
if (buf_size > 0) {
- url_setbufsize(pb, buf_size);
+ ffio_set_buf_size(pb, buf_size);
}
if (!fmt && (err = av_probe_input_buffer(pb, &fmt, filename, logctx, 0, logctx ? (*ic_ptr)->probesize : 0)) < 0) {
goto fail;
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)) {
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){
read_size = 0;
for(;;) {
if(url_interrupt_cb()){
- ret= AVERROR(EINTR);
+ ret= AVERROR_EXIT;
av_log(ic, AV_LOG_DEBUG, "interrupted\n");
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;
+ }
}
}
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);
}
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);
av_hex_dump(f, pkt->data, pkt->size);
}
+#if FF_API_PKT_DUMP
void av_pkt_dump(FILE *f, AVPacket *pkt, int dump_payload)
{
AVRational tb = { 1, AV_TIME_BASE };
pkt_dump_internal(NULL, f, 0, pkt, dump_payload, tb);
}
+#endif
void av_pkt_dump2(FILE *f, AVPacket *pkt, int dump_payload, AVStream *st)
{
pkt_dump_internal(NULL, f, 0, pkt, dump_payload, st->time_base);
}
+#if FF_API_PKT_DUMP
void av_pkt_dump_log(void *avcl, int level, AVPacket *pkt, int dump_payload)
{
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)
}
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);
+}