score_max = 0;
while ((fmt = av_oformat_next(fmt))) {
score = 0;
- if (fmt->name && short_name && !av_strcasecmp(fmt->name, short_name))
+ if (fmt->name && short_name && match_format(short_name, fmt->name))
score += 100;
if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type))
score += 10;
int64_t old_diff= FFABS(st->cur_dts - duration - pkt->pts);
int64_t new_diff= FFABS(st->cur_dts - pkt->pts);
if( old_diff < new_diff && old_diff < (duration>>3)
+ && st->codec->codec_type == AVMEDIA_TYPE_VIDEO
&& (!strcmp(s->iformat->name, "mpeg") ||
!strcmp(s->iformat->name, "mpegts"))){
pkt->pts += duration;
pkt->pts, pkt->dts, pkt->pos);
pkt->pts = pkt->dts = AV_NOPTS_VALUE;
+ pkt->pos = -1;
/* increment read pointer */
data += len;
size -= len;
out_pkt.dts = st->parser->dts;
out_pkt.pos = st->parser->pos;
+ if(st->need_parsing == AVSTREAM_PARSE_FULL_RAW)
+ out_pkt.pos = st->parser->frame_offset;
+
if (st->parser->key_frame == 1 ||
(st->parser->key_frame == -1 &&
st->parser->pict_type == AV_PICTURE_TYPE_I))
const int genpts = s->flags & AVFMT_FLAG_GENPTS;
int eof = 0;
int ret;
+ AVStream *st;
if (!genpts) {
ret = s->packet_buffer ? read_from_packet_buffer(&s->packet_buffer,
}
return_packet:
+
+ st = s->streams[pkt->stream_index];
+ if (st->skip_samples) {
+ uint8_t *p = av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
+ AV_WL32(p, st->skip_samples);
+ av_log(s, AV_LOG_DEBUG, "demuxer injecting skip %d\n", st->skip_samples);
+ st->skip_samples = 0;
+ }
+
if (is_relative(pkt->dts))
pkt->dts -= RELATIVE_TS_BASE;
if (is_relative(pkt->pts))
}
}
-static int has_codec_parameters(AVStream *st)
+static int has_codec_parameters(AVStream *st, const char **errmsg_ptr)
{
AVCodecContext *avctx = st->codec;
- int val;
+
+#define FAIL(errmsg) do { \
+ if (errmsg_ptr) \
+ *errmsg_ptr = errmsg; \
+ return 0; \
+ } while (0)
+
switch (avctx->codec_type) {
case AVMEDIA_TYPE_AUDIO:
- val = avctx->sample_rate && avctx->channels;
if (!avctx->frame_size && determinable_frame_size(avctx))
- return 0;
+ FAIL("unspecified sample size");
if (st->info->found_decoder >= 0 && avctx->sample_fmt == AV_SAMPLE_FMT_NONE)
- return 0;
+ FAIL("unspecified sample format");
+ if (!avctx->sample_rate)
+ FAIL("unspecified sample rate");
+ if (!avctx->channels)
+ FAIL("unspecified number of channels");
break;
case AVMEDIA_TYPE_VIDEO:
- val = avctx->width;
+ if (!avctx->width)
+ FAIL("unspecified size");
if (st->info->found_decoder >= 0 && avctx->pix_fmt == PIX_FMT_NONE)
- return 0;
+ FAIL("unspecified pixel format");
break;
case AVMEDIA_TYPE_DATA:
if(avctx->codec_id == CODEC_ID_NONE) return 1;
- default:
- val = 1;
- break;
}
- return avctx->codec_id != CODEC_ID_NONE && val != 0;
+
+ if (avctx->codec_id == CODEC_ID_NONE)
+ FAIL("unknown codec");
+ return 1;
}
static int has_decode_delay_been_guessed(AVStream *st)
{
- return st->codec->codec_id != CODEC_ID_H264 ||
- st->info->nb_decoded_frames >= 6;
+ if(st->codec->codec_id != CODEC_ID_H264) return 1;
+#if CONFIG_H264_DECODER
+ if(st->codec->has_b_frames &&
+ avpriv_h264_has_num_reorder_frames(st->codec) == st->codec->has_b_frames)
+ return 1;
+#endif
+ if(st->codec->has_b_frames<3)
+ return st->info->nb_decoded_frames >= 6;
+ else if(st->codec->has_b_frames<4)
+ return st->info->nb_decoded_frames >= 18;
+ else
+ return st->info->nb_decoded_frames >= 20;
}
/* returns 1 or 0 if or if not decoded data was returned, or a negative error */
while ((pkt.size > 0 || (!pkt.data && got_picture)) &&
ret >= 0 &&
- (!has_codec_parameters(st) ||
+ (!has_codec_parameters(st, NULL) ||
!has_decode_delay_been_guessed(st) ||
(!st->codec_info_nb_frames && st->codec->codec->capabilities & CODEC_CAP_CHANNEL_CONF))) {
got_picture = 0;
}
static int get_std_framerate(int i){
- if(i<60*12) return i*1001;
+ if(i<60*12) return (i+1)*1001;
else return ((const int[]){24,30,60,12,15,48})[i-60*12]*1000*12;
}
: &thread_opt);
//try to just open decoders, in case this is enough to get parameters
- if (!has_codec_parameters(st)) {
+ if (!has_codec_parameters(st, NULL)) {
if (codec && !st->codec->codec)
avcodec_open2(st->codec, codec, options ? &options[i]
: &thread_opt);
int fps_analyze_framecount = 20;
st = ic->streams[i];
- if (!has_codec_parameters(st))
+ if (!has_codec_parameters(st, NULL))
break;
/* if the timebase is coarse (like the usual millisecond precision
of mkv), we need to analyze more frames to reliably arrive at
// if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
// av_log(NULL, AV_LOG_ERROR, "%f\n", dts);
- for (i=1; i<FF_ARRAY_ELEMS(st->info->duration_error[0][0]); i++) {
+ for (i=0; i<FF_ARRAY_ELEMS(st->info->duration_error[0][0]); i++) {
int framerate= get_std_framerate(i);
double sdts= dts*framerate/(1001*12);
for(j=0; j<2; j++){
ret = -1; /* we could not have all the codec parameters before EOF */
for(i=0;i<ic->nb_streams;i++) {
+ const char *errmsg;
+
st = ic->streams[i];
/* flush the decoders */
err = try_decode_frame(st, &empty_pkt,
(options && i < orig_nb_streams) ?
&options[i] : NULL);
- } while (err > 0 && !has_codec_parameters(st));
+ } while (err > 0 && !has_codec_parameters(st, NULL));
if (err < 0) {
av_log(ic, AV_LOG_INFO,
}
}
- if (!has_codec_parameters(st)){
+ if (!has_codec_parameters(st, &errmsg)) {
char buf[256];
avcodec_string(buf, sizeof(buf), st->codec, 0);
av_log(ic, AV_LOG_WARNING,
- "Could not find codec parameters (%s)\n", buf);
+ "Could not find codec parameters for stream %d (%s): %s\n"
+ "Consider increasing the value for the 'analyzeduration' and 'probesize' options\n",
+ i, buf, errmsg);
} else {
ret = 0;
}
int num = 0;
double best_error= 0.01;
- for (j=1; j<FF_ARRAY_ELEMS(st->info->duration_error[0][0]); j++) {
+ for (j=0; j<FF_ARRAY_ELEMS(st->info->duration_error[0][0]); j++) {
int k;
if(st->info->codec_info_duration && st->info->codec_info_duration*av_q2d(st->time_base) < (1001*12.0)/get_std_framerate(j))
char *path, int path_size,
const char *url)
{
- const char *p, *ls, *at, *col, *brk;
+ const char *p, *ls, *ls2, *at, *col, *brk;
if (port_ptr) *port_ptr = -1;
if (proto_size > 0) proto[0] = 0;
/* separate path from hostname */
ls = strchr(p, '/');
+ ls2 = strchr(p, '?');
if(!ls)
- ls = strchr(p, '?');
+ ls = ls2;
+ else if (ls && ls2)
+ ls = FFMIN(ls, ls2);
if(ls)
av_strlcpy(path, ls, path_size);
else
return;
}
s->time_base = new_tb;
+ av_codec_set_pkt_timebase(s->codec, new_tb);
s->pts_wrap_bits = pts_wrap_bits;
}
else
return frame_sample_aspect_ratio;
}
+
+int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st,
+ const char *spec)
+{
+ if (*spec <= '9' && *spec >= '0') /* opt:index */
+ return strtol(spec, NULL, 0) == st->index;
+ else if (*spec == 'v' || *spec == 'a' || *spec == 's' || *spec == 'd' ||
+ *spec == 't') { /* opt:[vasdt] */
+ enum AVMediaType type;
+
+ 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;
+ default: av_assert0(0);
+ }
+ if (type != st->codec->codec_type)
+ return 0;
+ if (*spec++ == ':') { /* possibly followed by :index */
+ int i, index = strtol(spec, NULL, 0);
+ for (i = 0; i < s->nb_streams; i++)
+ if (s->streams[i]->codec->codec_type == type && index-- == 0)
+ return i == st->index;
+ return 0;
+ }
+ return 1;
+ } else if (*spec == 'p' && *(spec + 1) == ':') {
+ int prog_id, i, j;
+ char *endptr;
+ spec += 2;
+ prog_id = strtol(spec, &endptr, 0);
+ for (i = 0; i < s->nb_programs; i++) {
+ if (s->programs[i]->id != prog_id)
+ continue;
+
+ if (*endptr++ == ':') {
+ int stream_idx = strtol(endptr, NULL, 0);
+ return stream_idx >= 0 &&
+ stream_idx < s->programs[i]->nb_stream_indexes &&
+ st->index == s->programs[i]->stream_index[stream_idx];
+ }
+
+ for (j = 0; j < s->programs[i]->nb_stream_indexes; j++)
+ if (st->index == s->programs[i]->stream_index[j])
+ return 1;
+ }
+ return 0;
+ } else if (*spec == '#') {
+ int sid;
+ char *endptr;
+ sid = strtol(spec + 1, &endptr, 0);
+ if (!*endptr)
+ return st->id == sid;
+ } else if (!*spec) /* empty specifier, matches everything */
+ return 1;
+
+ av_log(s, AV_LOG_ERROR, "Invalid stream specifier: %s.\n", spec);
+ return AVERROR(EINVAL);
+}