/*
- * various utility functions for use within Libav
+ * various utility functions for use within FFmpeg
* Copyright (c) 2000, 2001, 2002 Fabrice Bellard
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg 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.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg 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 Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avio_internal.h"
#include "internal.h"
#include "libavcodec/internal.h"
+#include "libavcodec/raw.h"
#include "libavutil/opt.h"
#include "metadata.h"
#include "id3v2.h"
/**
* @file
- * various utility functions for use within Libav
+ * various utility functions for use within FFmpeg
*/
unsigned avformat_version(void)
const char *avformat_configuration(void)
{
- return LIBAV_CONFIGURATION;
+ return FFMPEG_CONFIGURATION;
}
const char *avformat_license(void)
{
#define LICENSE_PREFIX "libavformat license: "
- return LICENSE_PREFIX LIBAV_LICENSE + sizeof(LICENSE_PREFIX) - 1;
+ return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1;
}
/* fraction handling */
return filename && (av_get_frame_filename(buf, sizeof(buf), filename, 1)>=0);
}
-AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max)
+AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, int *score_ret)
{
AVProbeData lpd = *pd;
AVInputFormat *fmt1 = NULL, *fmt;
- int score, id3 = 0;
+ int score, score_max=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;
score = 0;
if (fmt1->read_probe) {
score = fmt1->read_probe(&lpd);
+ if(!score && fmt1->extensions && av_match_ext(lpd.filename, fmt1->extensions))
+ score = 1;
} else if (fmt1->extensions) {
if (av_match_ext(lpd.filename, fmt1->extensions)) {
score = 50;
}
}
- if (score > *score_max) {
- *score_max = score;
+ if (score > score_max) {
+ score_max = score;
fmt = fmt1;
- }else if (score == *score_max)
+ }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;
- }
- }
-
+ *score_ret= score_max;
return fmt;
}
+AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max)
+{
+ int score_ret;
+ AVInputFormat *fmt= av_probe_input_format3(pd, is_opened, &score_ret);
+ if(score_ret > *score_max){
+ *score_max= score_ret;
+ return fmt;
+ }else
+ return NULL;
+}
+
AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened){
int score=0;
return av_probe_input_format2(pd, is_opened, &score);
}
-static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st, AVProbeData *pd, int score)
+static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st, AVProbeData *pd)
{
static const struct {
const char *name; enum CodecID id; enum AVMediaType type;
{ "mpegvideo", CODEC_ID_MPEG2VIDEO, AVMEDIA_TYPE_VIDEO },
{ 0 }
};
- AVInputFormat *fmt = av_probe_input_format2(pd, 1, &score);
+ int score;
+ AVInputFormat *fmt = av_probe_input_format3(pd, 1, &score);
if (fmt) {
int i;
}
}
}
- return !!fmt;
+ return score;
}
/************************************************************/
if (pktl) {
*pkt = pktl->pkt;
- if(s->streams[pkt->stream_index]->codec->codec_id != CODEC_ID_PROBE ||
- !s->streams[pkt->stream_index]->probe_packets ||
- s->raw_packet_buffer_remaining_size < pkt->size){
- AVProbeData *pd = &s->streams[pkt->stream_index]->probe_data;
- av_freep(&pd->buf);
- pd->buf_size = 0;
+ if(s->streams[pkt->stream_index]->request_probe <= 0){
s->raw_packet_buffer = pktl->next;
s->raw_packet_buffer_remaining_size += pkt->size;
av_free(pktl);
if (!pktl || ret == AVERROR(EAGAIN))
return ret;
for (i = 0; i < s->nb_streams; i++)
- s->streams[i]->probe_packets = 0;
+ if(s->streams[i]->request_probe > 0)
+ s->streams[i]->request_probe = -1;
continue;
}
st= s->streams[pkt->stream_index];
break;
}
- if(!pktl && (st->codec->codec_id != CODEC_ID_PROBE ||
- !st->probe_packets))
+ if(!pktl && st->request_probe <= 0)
return ret;
add_to_pktbuf(&s->raw_packet_buffer, pkt, &s->raw_packet_buffer_end);
s->raw_packet_buffer_remaining_size -= pkt->size;
- if(st->codec->codec_id == CODEC_ID_PROBE){
+ if(st->request_probe>0){
AVProbeData *pd = &st->probe_data;
- av_log(s, AV_LOG_DEBUG, "probing stream %d\n", st->index);
+ int end;
+ av_log(s, AV_LOG_DEBUG, "probing stream %d pp:%d\n", st->index, st->probe_packets);
--st->probe_packets;
pd->buf = av_realloc(pd->buf, pd->buf_size+pkt->size+AVPROBE_PADDING_SIZE);
pd->buf_size += pkt->size;
memset(pd->buf+pd->buf_size, 0, AVPROBE_PADDING_SIZE);
- if(av_log2(pd->buf_size) != av_log2(pd->buf_size - pkt->size)){
- //FIXME we dont reduce score to 0 for the case of running out of buffer space in bytes
- set_codec_from_probe_data(s, st, pd, st->probe_packets > 0 ? AVPROBE_SCORE_MAX/4 : 0);
- if(st->codec->codec_id != CODEC_ID_PROBE){
+ end= s->raw_packet_buffer_remaining_size <= 0
+ || st->probe_packets<=0;
+
+ if(end || av_log2(pd->buf_size) != av_log2(pd->buf_size - pkt->size)){
+ int score= set_codec_from_probe_data(s, st, pd);
+ if( (st->codec->codec_id != CODEC_ID_NONE && score > AVPROBE_SCORE_MAX/4)
+ || end){
pd->buf_size=0;
av_freep(&pd->buf);
+ st->request_probe= -1;
+ if(st->codec->codec_id != CODEC_ID_NONE){
av_log(s, AV_LOG_DEBUG, "probed stream %d\n", st->index);
+ }else
+ av_log(s, AV_LOG_WARNING, "probed stream %d failed\n", st->index);
}
}
}
st= ic->streams[i];
st->cur_dts= st->first_dts;
st->last_IP_pts = AV_NOPTS_VALUE;
+ st->reference_dts = AV_NOPTS_VALUE;
}
}
/* 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;
(st->codec_info_nb_frames-2)*(int64_t)st->time_base.den,
st->info->codec_info_duration*(int64_t)st->time_base.num, 60000);
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
- if(st->codec->codec_id == CODEC_ID_RAWVIDEO && !st->codec->codec_tag && !st->codec->bits_per_coded_sample)
- st->codec->codec_tag= avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt);
+ if(st->codec->codec_id == CODEC_ID_RAWVIDEO && !st->codec->codec_tag && !st->codec->bits_per_coded_sample){
+ uint32_t tag= avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt);
+ if(ff_find_pix_fmt(ff_raw_pix_fmt_tags, tag) == st->codec->pix_fmt)
+ st->codec->codec_tag= tag;
+ }
// the check for tb_unreliable() is not completely correct, since this is not about handling
// a unreliable/inexact time base, but a time base that is finer than necessary, as e.g.
// ipmovie.c produces.
- if (tb_unreliable(st->codec) && st->info->duration_count > 15 && st->info->duration_gcd > 1 && !st->r_frame_rate.num)
+ if (tb_unreliable(st->codec) && st->info->duration_count > 15 && st->info->duration_gcd > FFMAX(1, st->time_base.den/(500LL*st->time_base.num)) && !st->r_frame_rate.num)
av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, st->time_base.den, st->time_base.num * st->info->duration_gcd, INT_MAX);
if (st->info->duration_count && !st->r_frame_rate.num
&& tb_unreliable(st->codec) /*&&
AVCodec **decoder_ret,
int flags)
{
- int i, nb_streams = ic->nb_streams, stream_number = 0;
+ int i, nb_streams = ic->nb_streams;
int ret = AVERROR_STREAM_NOT_FOUND, best_count = -1;
unsigned *program = NULL;
AVCodec *decoder = NULL, *best_decoder = NULL;
}
}
for (i = 0; i < nb_streams; i++) {
- AVStream *st = ic->streams[program ? program[i] : i];
+ int real_stream_index = program ? program[i] : i;
+ AVStream *st = ic->streams[real_stream_index];
AVCodecContext *avctx = st->codec;
if (avctx->codec_type != type)
continue;
- if (wanted_stream_nb >= 0 && stream_number++ != wanted_stream_nb)
+ if (wanted_stream_nb >= 0 && real_stream_index != 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);
+ decoder = avcodec_find_decoder(st->codec->codec_id);
if (!decoder) {
if (ret < 0)
ret = AVERROR_DECODER_NOT_FOUND;
if (best_count >= st->codec_info_nb_frames)
continue;
best_count = st->codec_info_nb_frames;
- ret = program ? program[i] : i;
+ ret = real_stream_index;
best_decoder = decoder;
if (program && i == nb_streams - 1 && ret < 0) {
program = NULL;
int delay = FFMAX(st->codec->has_b_frames, !!st->codec->max_b_frames);
int num, den, frame_size, i;
- av_dlog(s, "av_write_frame: pts:%"PRId64" dts:%"PRId64" cur_dts:%"PRId64" b:%d size:%d st:%d\n",
+ av_dlog(s, "compute_pkt_fields2: 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 AVERROR(EINVAL);*/
/* duration field */
if (pkt->duration == 0) {
av_log(s, AV_LOG_ERROR,
"Application provided invalid, non monotonically increasing dts to muxer in stream %d: %"PRId64" >= %"PRId64"\n",
st->index, st->cur_dts, pkt->dts);
- return -1;
+ return AVERROR(EINVAL);
}
if(pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE && pkt->pts < pkt->dts){
av_log(s, AV_LOG_ERROR, "pts < dts in stream %d\n", st->index);
- return -1;
+ return AVERROR(EINVAL);
}
// av_log(s, AV_LOG_DEBUG, "av_write_frame: pts2:%"PRId64" dts2:%"PRId64"\n", pkt->pts, pkt->dts);
return ret;
ret= s->oformat->write_packet(s, pkt);
+ if(!ret)
+ ret= url_ferror(s->pb);
return ret;
}
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);