NULL
};
+typedef struct BenchmarkTimeStamps {
+ int64_t real_usec;
+ int64_t user_usec;
+ int64_t sys_usec;
+} BenchmarkTimeStamps;
+
static void do_video_stats(OutputStream *ost, int frame_size);
-static int64_t getutime(void);
+static BenchmarkTimeStamps get_benchmark_time_stamps(void);
static int64_t getmaxrss(void);
static int ifilter_has_all_input_formats(FilterGraph *fg);
static int want_sdp = 1;
-static int current_time;
+static BenchmarkTimeStamps current_time;
AVIOContext *progress_avio = NULL;
static uint8_t *subtitle_out;
}
}
-void sub2video_update(InputStream *ist, AVSubtitle *sub)
+void sub2video_update(InputStream *ist, int64_t heartbeat_pts, AVSubtitle *sub)
{
AVFrame *frame = ist->sub2video.frame;
int8_t *dst;
AV_TIME_BASE_Q, ist->st->time_base);
num_rects = sub->num_rects;
} else {
- pts = ist->sub2video.end_pts;
+ /* If we are initializing the system, utilize current heartbeat
+ PTS as the start time, and show until the following subpicture
+ is received. Otherwise, utilize the previous subpicture's end time
+ as the fall-back value. */
+ pts = ist->sub2video.initialize ?
+ heartbeat_pts : ist->sub2video.end_pts;
end_pts = INT64_MAX;
num_rects = 0;
}
sub2video_copy_rect(dst, dst_linesize, frame->width, frame->height, sub->rects[i]);
sub2video_push_ref(ist, pts);
ist->sub2video.end_pts = end_pts;
+ ist->sub2video.initialize = 0;
}
static void sub2video_heartbeat(InputStream *ist, int64_t pts)
/* do not send the heartbeat frame if the subtitle is already ahead */
if (pts2 <= ist2->sub2video.last_pts)
continue;
- if (pts2 >= ist2->sub2video.end_pts || !ist2->sub2video.frame->data[0])
- sub2video_update(ist2, NULL);
+ if (pts2 >= ist2->sub2video.end_pts || ist2->sub2video.initialize)
+ /* if we have hit the end of the current displayed subpicture,
+ or if we need to initialize the system, update the
+ overlayed subpicture and its start/end times */
+ sub2video_update(ist2, pts2 + 1, NULL);
for (j = 0, nb_reqs = 0; j < ist2->nb_filters; j++)
nb_reqs += av_buffersrc_get_nb_failed_requests(ist2->filters[j]->filter);
if (nb_reqs)
int ret;
if (ist->sub2video.end_pts < INT64_MAX)
- sub2video_update(ist, NULL);
+ sub2video_update(ist, INT64_MAX, NULL);
for (i = 0; i < ist->nb_filters; i++) {
ret = av_buffersrc_add_frame(ist->filters[i]->filter, NULL);
if (ret != AVERROR_EOF && ret < 0)
av_frame_free(&ost->last_frame);
av_dict_free(&ost->encoder_opts);
- av_parser_close(ost->parser);
- avcodec_free_context(&ost->parser_avctx);
-
av_freep(&ost->forced_keyframes);
av_expr_free(ost->forced_keyframes_pexpr);
av_freep(&ost->avfilter);
ost->audio_channels_mapped = 0;
av_dict_free(&ost->sws_dict);
+ av_dict_free(&ost->swr_opts);
avcodec_free_context(&ost->enc_ctx);
avcodec_parameters_free(&ost->ref_par);
static void update_benchmark(const char *fmt, ...)
{
if (do_benchmark_all) {
- int64_t t = getutime();
+ BenchmarkTimeStamps t = get_benchmark_time_stamps();
va_list va;
char buf[1024];
va_start(va, fmt);
vsnprintf(buf, sizeof(buf), fmt, va);
va_end(va);
- av_log(NULL, AV_LOG_INFO, "bench: %8"PRIu64" %s \n", t - current_time, buf);
+ av_log(NULL, AV_LOG_INFO,
+ "bench: %8" PRIu64 " user %8" PRIu64 " sys %8" PRIu64 " real %s \n",
+ t.user_usec - current_time.user_usec,
+ t.sys_usec - current_time.sys_usec,
+ t.real_usec - current_time.real_usec, buf);
}
current_time = t;
}
if (ret < 0)
exit_program(1);
}
- ret = av_packet_ref(&tmp_pkt, pkt);
+ ret = av_packet_make_refcounted(pkt);
if (ret < 0)
exit_program(1);
+ av_packet_move_ref(&tmp_pkt, pkt);
av_fifo_generic_write(ost->muxing_queue, &tmp_pkt, sizeof(tmp_pkt), NULL);
- av_packet_unref(pkt);
return;
}
- FFMIN3(pkt->pts, pkt->dts, ost->last_mux_dts + 1)
- FFMAX3(pkt->pts, pkt->dts, ost->last_mux_dts + 1);
}
- if ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
+ if ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) &&
pkt->dts != AV_NOPTS_VALUE &&
!(st->codecpar->codec_id == AV_CODEC_ID_VP9 && ost->stream_copy) &&
ost->last_mux_dts != AV_NOPTS_VALUE) {
int64_t max = ost->last_mux_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT);
if (pkt->dts < max) {
int loglevel = max - pkt->dts > 2 || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG;
+ if (exit_on_error)
+ loglevel = AV_LOG_ERROR;
av_log(s, loglevel, "Non-monotonous DTS in output stream "
"%d:%d; previous: %"PRId64", current: %"PRId64"; ",
ost->file_index, ost->st->index, ost->last_mux_dts, pkt->dts);
if (!ost->filters_script &&
!ost->filters &&
+ (nb_filtergraphs == 0 || !filtergraphs[0]->graph_desc) &&
next_picture &&
ist &&
lrintf(next_picture->pkt_duration * av_q2d(ist->st->time_base) / av_q2d(enc->time_base)) > 0) {
format_video_sync != VSYNC_PASSTHROUGH &&
format_video_sync != VSYNC_DROP) {
if (delta0 < -0.6) {
- av_log(NULL, AV_LOG_WARNING, "Past duration %f too large\n", -delta0);
+ av_log(NULL, AV_LOG_VERBOSE, "Past duration %f too large\n", -delta0);
} else
av_log(NULL, AV_LOG_DEBUG, "Clipping frame in rate conversion by %f\n", -delta0);
sync_ipts = ost->sync_opts;
av_log(NULL, AV_LOG_DEBUG, "Not duplicating %d initial frames\n", (int)lrintf(delta0));
delta = duration;
delta0 = 0;
- ost->sync_opts = lrint(sync_ipts);
+ ost->sync_opts = llrint(sync_ipts);
}
case VSYNC_CFR:
// FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c
else if (delta > 1.1) {
nb_frames = lrintf(delta);
if (delta0 > 1.1)
- nb0_frames = lrintf(delta0 - 0.6);
+ nb0_frames = llrintf(delta0 - 0.6);
}
break;
case VSYNC_VFR:
if (delta <= -0.6)
nb_frames = 0;
else if (delta > 0.6)
- ost->sync_opts = lrint(sync_ipts);
+ ost->sync_opts = llrint(sync_ipts);
break;
case VSYNC_DROP:
case VSYNC_PASSTHROUGH:
- ost->sync_opts = lrint(sync_ipts);
+ ost->sync_opts = llrint(sync_ipts);
break;
default:
av_assert0(0);
}
ost->last_dropped = nb_frames == nb0_frames && next_picture;
- /* duplicates frame if needed */
- for (i = 0; i < nb_frames; i++) {
- AVFrame *in_picture;
- av_init_packet(&pkt);
- pkt.data = NULL;
- pkt.size = 0;
-
- if (i < nb0_frames && ost->last_frame) {
- in_picture = ost->last_frame;
- } else
- in_picture = next_picture;
+ /* duplicates frame if needed */
+ for (i = 0; i < nb_frames; i++) {
+ AVFrame *in_picture;
+ int forced_keyframe = 0;
+ double pts_time;
+ av_init_packet(&pkt);
+ pkt.data = NULL;
+ pkt.size = 0;
- if (!in_picture)
- return;
+ if (i < nb0_frames && ost->last_frame) {
+ in_picture = ost->last_frame;
+ } else
+ in_picture = next_picture;
- in_picture->pts = ost->sync_opts;
+ if (!in_picture)
+ return;
-#if 1
- if (!check_recording_time(ost))
-#else
- if (ost->frame_number >= ost->max_frames)
-#endif
- return;
+ in_picture->pts = ost->sync_opts;
- {
- int forced_keyframe = 0;
- double pts_time;
+ if (!check_recording_time(ost))
+ return;
if (enc->flags & (AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME) &&
ost->top_field_first >= 0)
in_picture->quality = enc->global_quality;
in_picture->pict_type = 0;
+ if (ost->forced_kf_ref_pts == AV_NOPTS_VALUE &&
+ in_picture->pts != AV_NOPTS_VALUE)
+ ost->forced_kf_ref_pts = in_picture->pts;
+
pts_time = in_picture->pts != AV_NOPTS_VALUE ?
- in_picture->pts * av_q2d(enc->time_base) : NAN;
+ (in_picture->pts - ost->forced_kf_ref_pts) * av_q2d(enc->time_base) : NAN;
if (ost->forced_kf_index < ost->forced_kf_count &&
in_picture->pts >= ost->forced_kf_pts[ost->forced_kf_index]) {
ost->forced_kf_index++;
ost->forced_keyframes_expr_const_values[FKF_N] += 1;
} else if ( ost->forced_keyframes
&& !strncmp(ost->forced_keyframes, "source", 6)
- && in_picture->key_frame==1) {
+ && in_picture->key_frame==1
+ && !i) {
forced_keyframe = 1;
}
ret = avcodec_send_frame(enc, in_picture);
if (ret < 0)
goto error;
+ // Make sure Closed Captions will not be duplicated
+ av_frame_remove_side_data(in_picture, AV_FRAME_DATA_A53_CC);
while (1) {
ret = avcodec_receive_packet(enc, &pkt);
fprintf(ost->logfile, "%s", enc->stats_out);
}
}
- }
- ost->sync_opts++;
- /*
- * For video, number of frames in == number of packets out.
- * But there may be reordering, so we can't throw away frames on encoder
- * flush, we need to limit them here, before they go into encoder.
- */
- ost->frame_number++;
+ ost->sync_opts++;
+ /*
+ * For video, number of frames in == number of packets out.
+ * But there may be reordering, so we can't throw away frames on encoder
+ * flush, we need to limit them here, before they go into encoder.
+ */
+ ost->frame_number++;
- if (vstats_filename && frame_size)
- do_video_stats(ost, frame_size);
- }
+ if (vstats_filename && frame_size)
+ do_video_stats(ost, frame_size);
+ }
if (!ost->last_frame)
ost->last_frame = av_frame_alloc();
av_rescale_q(filtered_frame->pts, filter_tb, enc->time_base) -
av_rescale_q(start_time, AV_TIME_BASE_Q, enc->time_base);
}
- //if (ost->source_index >= 0)
- // *filtered_frame= *input_streams[ost->source_index]->decoded_frame; //for me_threshold
switch (av_buffersink_get_type(filter)) {
case AVMEDIA_TYPE_VIDEO:
static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time)
{
- char buf[1024];
- AVBPrint buf_script;
+ AVBPrint buf, buf_script;
OutputStream *ost;
AVFormatContext *oc;
int64_t total_size;
static int64_t last_time = -1;
static int qp_histogram[52];
int hours, mins, secs, us;
+ const char *hours_sign;
int ret;
float t;
if (total_size <= 0) // FIXME improve avio_size() so it works with non seekable output too
total_size = avio_tell(oc->pb);
- buf[0] = '\0';
vid = 0;
- av_bprint_init(&buf_script, 0, 1);
+ av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
+ av_bprint_init(&buf_script, 0, AV_BPRINT_SIZE_AUTOMATIC);
for (i = 0; i < nb_output_streams; i++) {
float q = -1;
ost = output_streams[i];
q = ost->quality / (float) FF_QP2LAMBDA;
if (vid && enc->codec_type == AVMEDIA_TYPE_VIDEO) {
- snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "q=%2.1f ", q);
+ av_bprintf(&buf, "q=%2.1f ", q);
av_bprintf(&buf_script, "stream_%d_%d_q=%.1f\n",
ost->file_index, ost->index, q);
}
frame_number = ost->frame_number;
fps = t > 1 ? frame_number / t : 0;
- snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "frame=%5d fps=%3.*f q=%3.1f ",
+ av_bprintf(&buf, "frame=%5d fps=%3.*f q=%3.1f ",
frame_number, fps < 9.95, fps, q);
av_bprintf(&buf_script, "frame=%d\n", frame_number);
- av_bprintf(&buf_script, "fps=%.1f\n", fps);
+ av_bprintf(&buf_script, "fps=%.2f\n", fps);
av_bprintf(&buf_script, "stream_%d_%d_q=%.1f\n",
ost->file_index, ost->index, q);
if (is_last_report)
- snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "L");
+ av_bprintf(&buf, "L");
if (qp_hist) {
int j;
int qp = lrintf(q);
if (qp >= 0 && qp < FF_ARRAY_ELEMS(qp_histogram))
qp_histogram[qp]++;
for (j = 0; j < 32; j++)
- snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%X", av_log2(qp_histogram[j] + 1));
+ av_bprintf(&buf, "%X", av_log2(qp_histogram[j] + 1));
}
if ((enc->flags & AV_CODEC_FLAG_PSNR) && (ost->pict_type != AV_PICTURE_TYPE_NONE || is_last_report)) {
double scale, scale_sum = 0;
double p;
char type[3] = { 'Y','U','V' };
- snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "PSNR=");
+ av_bprintf(&buf, "PSNR=");
for (j = 0; j < 3; j++) {
if (is_last_report) {
error = enc->error[j];
error_sum += error;
scale_sum += scale;
p = psnr(error / scale);
- snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%c:%2.2f ", type[j], p);
+ av_bprintf(&buf, "%c:%2.2f ", type[j], p);
av_bprintf(&buf_script, "stream_%d_%d_psnr_%c=%2.2f\n",
ost->file_index, ost->index, type[j] | 32, p);
}
p = psnr(error_sum / scale_sum);
- snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "*:%2.2f ", psnr(error_sum / scale_sum));
+ av_bprintf(&buf, "*:%2.2f ", psnr(error_sum / scale_sum));
av_bprintf(&buf_script, "stream_%d_%d_psnr_all=%2.2f\n",
ost->file_index, ost->index, p);
}
secs %= 60;
hours = mins / 60;
mins %= 60;
+ hours_sign = (pts < 0) ? "-" : "";
bitrate = pts && total_size >= 0 ? total_size * 8 / (pts / 1000.0) : -1;
speed = t != 0.0 ? (double)pts / AV_TIME_BASE / t : -1;
- if (total_size < 0) snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
- "size=N/A time=");
- else snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
- "size=%8.0fkB time=", total_size / 1024.0);
- if (pts < 0)
- snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "-");
- snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
- "%02d:%02d:%02d.%02d ", hours, mins, secs,
- (100 * us) / AV_TIME_BASE);
+ if (total_size < 0) av_bprintf(&buf, "size=N/A time=");
+ else av_bprintf(&buf, "size=%8.0fkB time=", total_size / 1024.0);
+ if (pts == AV_NOPTS_VALUE) {
+ av_bprintf(&buf, "N/A ");
+ } else {
+ av_bprintf(&buf, "%s%02d:%02d:%02d.%02d ",
+ hours_sign, hours, mins, secs, (100 * us) / AV_TIME_BASE);
+ }
if (bitrate < 0) {
- snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),"bitrate=N/A");
+ av_bprintf(&buf, "bitrate=N/A");
av_bprintf(&buf_script, "bitrate=N/A\n");
}else{
- snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),"bitrate=%6.1fkbits/s", bitrate);
+ av_bprintf(&buf, "bitrate=%6.1fkbits/s", bitrate);
av_bprintf(&buf_script, "bitrate=%6.1fkbits/s\n", bitrate);
}
if (total_size < 0) av_bprintf(&buf_script, "total_size=N/A\n");
else av_bprintf(&buf_script, "total_size=%"PRId64"\n", total_size);
- av_bprintf(&buf_script, "out_time_ms=%"PRId64"\n", pts);
- av_bprintf(&buf_script, "out_time=%02d:%02d:%02d.%06d\n",
- hours, mins, secs, us);
+ if (pts == AV_NOPTS_VALUE) {
+ av_bprintf(&buf_script, "out_time_us=N/A\n");
+ av_bprintf(&buf_script, "out_time_ms=N/A\n");
+ av_bprintf(&buf_script, "out_time=N/A\n");
+ } else {
+ av_bprintf(&buf_script, "out_time_us=%"PRId64"\n", pts);
+ av_bprintf(&buf_script, "out_time_ms=%"PRId64"\n", pts);
+ av_bprintf(&buf_script, "out_time=%s%02d:%02d:%02d.%06d\n",
+ hours_sign, hours, mins, secs, us);
+ }
if (nb_frames_dup || nb_frames_drop)
- snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " dup=%d drop=%d",
- nb_frames_dup, nb_frames_drop);
+ av_bprintf(&buf, " dup=%d drop=%d", nb_frames_dup, nb_frames_drop);
av_bprintf(&buf_script, "dup_frames=%d\n", nb_frames_dup);
av_bprintf(&buf_script, "drop_frames=%d\n", nb_frames_drop);
if (speed < 0) {
- snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf)," speed=N/A");
+ av_bprintf(&buf, " speed=N/A");
av_bprintf(&buf_script, "speed=N/A\n");
} else {
- snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf)," speed=%4.3gx", speed);
+ av_bprintf(&buf, " speed=%4.3gx", speed);
av_bprintf(&buf_script, "speed=%4.3gx\n", speed);
}
if (print_stats || is_last_report) {
const char end = is_last_report ? '\n' : '\r';
if (print_stats==1 && AV_LOG_INFO > av_log_get_level()) {
- fprintf(stderr, "%s %c", buf, end);
+ fprintf(stderr, "%s %c", buf.str, end);
} else
- av_log(NULL, AV_LOG_INFO, "%s %c", buf, end);
+ av_log(NULL, AV_LOG_INFO, "%s %c", buf.str, end);
- fflush(stderr);
+ fflush(stderr);
}
+ av_bprint_finalize(&buf, NULL);
if (progress_avio) {
av_bprintf(&buf_script, "progress=%s\n",
print_final_stats(total_size);
}
+static void ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *par)
+{
+ // We never got any input. Set a fake format, which will
+ // come from libavformat.
+ ifilter->format = par->format;
+ ifilter->sample_rate = par->sample_rate;
+ ifilter->channels = par->channels;
+ ifilter->channel_layout = par->channel_layout;
+ ifilter->width = par->width;
+ ifilter->height = par->height;
+ ifilter->sample_aspect_ratio = par->sample_aspect_ratio;
+}
+
static void flush_encoders(void)
{
int i, ret;
int x;
for (x = 0; x < fg->nb_inputs; x++) {
InputFilter *ifilter = fg->inputs[x];
- if (ifilter->format < 0) {
- AVCodecParameters *par = ifilter->ist->st->codecpar;
- // We never got any input. Set a fake format, which will
- // come from libavformat.
- ifilter->format = par->format;
- ifilter->sample_rate = par->sample_rate;
- ifilter->channels = par->channels;
- ifilter->channel_layout = par->channel_layout;
- ifilter->width = par->width;
- ifilter->height = par->height;
- ifilter->sample_aspect_ratio = par->sample_aspect_ratio;
- }
+ if (ifilter->format < 0)
+ ifilter_parameters_from_codecpar(ifilter, ifilter->ist->st->codecpar);
}
if (!ifilter_has_all_input_formats(fg))
}
}
- if (enc->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <= 1)
- continue;
-
if (enc->codec_type != AVMEDIA_TYPE_VIDEO && enc->codec_type != AVMEDIA_TYPE_AUDIO)
continue;
av_assert0(0);
}
- av_init_packet(&pkt);
- pkt.data = NULL;
- pkt.size = 0;
+ av_init_packet(&pkt);
+ pkt.data = NULL;
+ pkt.size = 0;
- update_benchmark(NULL);
+ update_benchmark(NULL);
- while ((ret = avcodec_receive_packet(enc, &pkt)) == AVERROR(EAGAIN)) {
- ret = avcodec_send_frame(enc, NULL);
- if (ret < 0) {
- av_log(NULL, AV_LOG_FATAL, "%s encoding failed: %s\n",
- desc,
- av_err2str(ret));
- exit_program(1);
- }
- }
-
- update_benchmark("flush_%s %d.%d", desc, ost->file_index, ost->index);
- if (ret < 0 && ret != AVERROR_EOF) {
+ while ((ret = avcodec_receive_packet(enc, &pkt)) == AVERROR(EAGAIN)) {
+ ret = avcodec_send_frame(enc, NULL);
+ if (ret < 0) {
av_log(NULL, AV_LOG_FATAL, "%s encoding failed: %s\n",
desc,
av_err2str(ret));
exit_program(1);
}
- if (ost->logfile && enc->stats_out) {
- fprintf(ost->logfile, "%s", enc->stats_out);
- }
- if (ret == AVERROR_EOF) {
- output_packet(of, &pkt, ost, 1);
- break;
- }
- if (ost->finished & MUXER_FINISHED) {
- av_packet_unref(&pkt);
- continue;
- }
- av_packet_rescale_ts(&pkt, enc->time_base, ost->mux_timebase);
- pkt_size = pkt.size;
- output_packet(of, &pkt, ost, 0);
- if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO && vstats_filename) {
- do_video_stats(ost, pkt_size);
- }
+ }
+
+ update_benchmark("flush_%s %d.%d", desc, ost->file_index, ost->index);
+ if (ret < 0 && ret != AVERROR_EOF) {
+ av_log(NULL, AV_LOG_FATAL, "%s encoding failed: %s\n",
+ desc,
+ av_err2str(ret));
+ exit_program(1);
+ }
+ if (ost->logfile && enc->stats_out) {
+ fprintf(ost->logfile, "%s", enc->stats_out);
+ }
+ if (ret == AVERROR_EOF) {
+ output_packet(of, &pkt, ost, 1);
+ break;
+ }
+ if (ost->finished & MUXER_FINISHED) {
+ av_packet_unref(&pkt);
+ continue;
+ }
+ av_packet_rescale_ts(&pkt, enc->time_base, ost->mux_timebase);
+ pkt_size = pkt.size;
+ output_packet(of, &pkt, ost, 0);
+ if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO && vstats_filename) {
+ do_video_stats(ost, pkt_size);
+ }
}
}
}
InputFile *f = input_files [ist->file_index];
int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time;
int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->mux_timebase);
- AVPacket opkt = { 0 };
-
- av_init_packet(&opkt);
+ AVPacket opkt;
// EOF: flush output bitstream filters.
if (!pkt) {
+ av_init_packet(&opkt);
+ opkt.data = NULL;
+ opkt.size = 0;
output_packet(of, &opkt, ost, 1);
return;
}
if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO)
ost->sync_opts++;
+ if (av_packet_ref(&opkt, pkt) < 0)
+ exit_program(1);
+
if (pkt->pts != AV_NOPTS_VALUE)
opkt.pts = av_rescale_q(pkt->pts, ist->st->time_base, ost->mux_timebase) - ost_tb_start_time;
- else
- opkt.pts = AV_NOPTS_VALUE;
- if (pkt->dts == AV_NOPTS_VALUE)
+ if (pkt->dts == AV_NOPTS_VALUE) {
opkt.dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ost->mux_timebase);
- else
- opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->mux_timebase);
- opkt.dts -= ost_tb_start_time;
-
- if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && pkt->dts != AV_NOPTS_VALUE) {
+ } else if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
int duration = av_get_audio_frame_duration(ist->dec_ctx, pkt->size);
if(!duration)
duration = ist->dec_ctx->frame_size;
- opkt.dts = opkt.pts = av_rescale_delta(ist->st->time_base, pkt->dts,
- (AVRational){1, ist->dec_ctx->sample_rate}, duration, &ist->filter_in_rescale_delta_last,
- ost->mux_timebase) - ost_tb_start_time;
- }
+ opkt.dts = av_rescale_delta(ist->st->time_base, pkt->dts,
+ (AVRational){1, ist->dec_ctx->sample_rate}, duration,
+ &ist->filter_in_rescale_delta_last, ost->mux_timebase);
+ /* dts will be set immediately afterwards to what pts is now */
+ opkt.pts = opkt.dts - ost_tb_start_time;
+ } else
+ opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->mux_timebase);
+ opkt.dts -= ost_tb_start_time;
opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->mux_timebase);
- opkt.flags = pkt->flags;
- // FIXME remove the following 2 lines they shall be replaced by the bitstream filters
- if ( ost->st->codecpar->codec_id != AV_CODEC_ID_H264
- && ost->st->codecpar->codec_id != AV_CODEC_ID_MPEG1VIDEO
- && ost->st->codecpar->codec_id != AV_CODEC_ID_MPEG2VIDEO
- && ost->st->codecpar->codec_id != AV_CODEC_ID_VC1
- ) {
- int ret = av_parser_change(ost->parser, ost->parser_avctx,
- &opkt.data, &opkt.size,
- pkt->data, pkt->size,
- pkt->flags & AV_PKT_FLAG_KEY);
- if (ret < 0) {
- av_log(NULL, AV_LOG_FATAL, "av_parser_change failed: %s\n",
- av_err2str(ret));
- exit_program(1);
- }
- if (ret) {
- opkt.buf = av_buffer_create(opkt.data, opkt.size, av_buffer_default_free, NULL, 0);
- if (!opkt.buf)
- exit_program(1);
- }
- } else {
- opkt.data = pkt->data;
- opkt.size = pkt->size;
- }
- av_copy_packet_side_data(&opkt, pkt);
-
output_packet(of, &opkt, ost, 0);
}
if (ret < 0 && exit_on_error)
exit_program(1);
- if (exit_on_error && *got_output && ist) {
+ if (*got_output && ist) {
if (ist->decoded_frame->decode_error_flags || (ist->decoded_frame->flags & AV_FRAME_FLAG_CORRUPT)) {
- av_log(NULL, AV_LOG_FATAL, "%s: corrupt decoded frame in stream %d\n", input_files[ist->file_index]->ctx->url, ist->st->index);
- exit_program(1);
+ av_log(NULL, exit_on_error ? AV_LOG_FATAL : AV_LOG_WARNING,
+ "%s: corrupt decoded frame in stream %d\n", input_files[ist->file_index]->ctx->url, ist->st->index);
+ if (exit_on_error)
+ exit_program(1);
}
}
}
/* determine if the parameters for this input changed */
need_reinit = ifilter->format != frame->format;
- if (!!ifilter->hw_frames_ctx != !!frame->hw_frames_ctx ||
- (ifilter->hw_frames_ctx && ifilter->hw_frames_ctx->data != frame->hw_frames_ctx->data))
- need_reinit = 1;
switch (ifilter->ist->st->codecpar->codec_type) {
case AVMEDIA_TYPE_AUDIO:
break;
}
+ if (!ifilter->ist->reinit_filters && fg->graph)
+ need_reinit = 0;
+
+ if (!!ifilter->hw_frames_ctx != !!frame->hw_frames_ctx ||
+ (ifilter->hw_frames_ctx && ifilter->hw_frames_ctx->data != frame->hw_frames_ctx->data))
+ need_reinit = 1;
+
if (need_reinit) {
ret = ifilter_parameters_from_frame(ifilter, frame);
if (ret < 0)
ret = reap_filters(1);
if (ret < 0 && ret != AVERROR_EOF) {
- char errbuf[128];
- av_strerror(ret, errbuf, sizeof(errbuf));
-
- av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", errbuf);
+ av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret));
return ret;
}
static int ifilter_send_eof(InputFilter *ifilter, int64_t pts)
{
- int i, j, ret;
+ int ret;
ifilter->eof = 1;
return ret;
} else {
// the filtergraph was never configured
- FilterGraph *fg = ifilter->graph;
- for (i = 0; i < fg->nb_inputs; i++)
- if (!fg->inputs[i]->eof)
- break;
- if (i == fg->nb_inputs) {
- // All the input streams have finished without the filtergraph
- // ever being configured.
- // Mark the output streams as finished.
- for (j = 0; j < fg->nb_outputs; j++)
- finish_output_stream(fg->outputs[j]->ost);
+ if (ifilter->format < 0)
+ ifilter_parameters_from_codecpar(ifilter, ifilter->ist->st->codecpar);
+ if (ifilter->format < 0 && (ifilter->type == AVMEDIA_TYPE_AUDIO || ifilter->type == AVMEDIA_TYPE_VIDEO)) {
+ av_log(NULL, AV_LOG_ERROR, "Cannot determine format of input stream %d:%d after EOF\n", ifilter->ist->file_index, ifilter->ist->st->index);
+ return AVERROR_INVALIDDATA;
}
}
ist->samples_decoded += decoded_frame->nb_samples;
ist->frames_decoded++;
-#if 1
/* increment next_dts to use for the case where the input stream does not
have timestamps or there are multiple frames in the packet */
ist->next_pts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) /
avctx->sample_rate;
ist->next_dts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) /
avctx->sample_rate;
-#endif
if (decoded_frame->pts != AV_NOPTS_VALUE) {
decoded_frame_tb = ist->st->time_base;
return ret;
if (ist->sub2video.frame) {
- sub2video_update(ist, &subtitle);
+ sub2video_update(ist, INT64_MIN, &subtitle);
} else if (ist->nb_filters) {
if (!ist->sub2video.sub_queue)
ist->sub2video.sub_queue = av_fifo_alloc(8 * sizeof(AVSubtitle));
ist->dts = ist->next_dts;
switch (ist->dec_ctx->codec_type) {
case AVMEDIA_TYPE_AUDIO:
- ist->next_dts += ((int64_t)AV_TIME_BASE * ist->dec_ctx->frame_size) /
- ist->dec_ctx->sample_rate;
+ av_assert1(pkt->duration >= 0);
+ if (ist->dec_ctx->sample_rate) {
+ ist->next_dts += ((int64_t)AV_TIME_BASE * ist->dec_ctx->frame_size) /
+ ist->dec_ctx->sample_rate;
+ } else {
+ ist->next_dts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q);
+ }
break;
case AVMEDIA_TYPE_VIDEO:
if (ist->framerate.num) {
if (avio_open2(&sdp_pb, sdp_filename, AVIO_FLAG_WRITE, &int_cb, NULL) < 0) {
av_log(NULL, AV_LOG_ERROR, "Failed to open sdp file '%s'\n", sdp_filename);
} else {
- avio_printf(sdp_pb, "SDP:\n%s", sdp);
+ avio_print(sdp_pb, sdp);
avio_closep(&sdp_pb);
av_freep(&sdp_filename);
}
"Error setting up codec context options.\n");
return ret;
}
- avcodec_parameters_from_context(par_src, ost->enc_ctx);
+
+ ret = avcodec_parameters_from_context(par_src, ost->enc_ctx);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_FATAL,
+ "Error getting reference codec parameters.\n");
+ return ret;
+ }
if (!codec_tag) {
unsigned int codec_tag_tmp;
av_display_rotation_set((int32_t *)sd, -ost->rotate_override_value);
}
- ost->parser = av_parser_init(par_dst->codec_id);
- ost->parser_avctx = avcodec_alloc_context3(NULL);
- if (!ost->parser_avctx)
- return AVERROR(ENOMEM);
-
switch (par_dst->codec_type) {
case AVMEDIA_TYPE_AUDIO:
if (audio_volume != 256) {
"if you want a different framerate.\n",
ost->file_index, ost->index);
}
-// ost->frame_rate = ist->st->avg_frame_rate.num ? ist->st->avg_frame_rate : (AVRational){25, 1};
+
if (ost->enc->supported_framerates && !ost->force_fps) {
int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates);
ost->frame_rate = ost->enc->supported_framerates[idx];
av_log(oc, AV_LOG_WARNING, "Frame rate very high for a muxer not efficiently supporting it.\n"
"Please consider specifying a lower framerate, a different muxer or -vsync 2\n");
}
- for (j = 0; j < ost->forced_kf_count; j++)
- ost->forced_kf_pts[j] = av_rescale_q(ost->forced_kf_pts[j],
- AV_TIME_BASE_Q,
- enc_ctx->time_base);
enc_ctx->width = av_buffersink_get_w(ost->filter->filter);
enc_ctx->height = av_buffersink_get_h(ost->filter->filter);
enc_ctx->bits_per_raw_sample = frame_bits_per_raw_sample;
}
+ if (ost->top_field_first == 0) {
+ enc_ctx->field_order = AV_FIELD_BB;
+ } else if (ost->top_field_first == 1) {
+ enc_ctx->field_order = AV_FIELD_TT;
+ }
+
if (ost->forced_keyframes) {
if (!strncmp(ost->forced_keyframes, "expr:", 5)) {
ret = av_expr_parse(&ost->forced_keyframes_pexpr, ost->forced_keyframes+5,
ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_N] = NAN;
ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_T] = NAN;
- // Don't parse the 'forced_keyframes' in case of 'keep-source-keyframes',
- // parse it only for static kf timings
+ // Don't parse the 'forced_keyframes' in case of 'keep-source-keyframes',
+ // parse it only for static kf timings
} else if(strncmp(ost->forced_keyframes, "source", 6)) {
parse_forced_key_frames(ost->forced_keyframes, ost, ost->enc_ctx);
}
return ret;
}
}
+ if (ist && ist->dec->type == AVMEDIA_TYPE_SUBTITLE && ost->enc->type == AVMEDIA_TYPE_SUBTITLE) {
+ int input_props = 0, output_props = 0;
+ AVCodecDescriptor const *input_descriptor =
+ avcodec_descriptor_get(dec->codec_id);
+ AVCodecDescriptor const *output_descriptor =
+ avcodec_descriptor_get(ost->enc_ctx->codec_id);
+ if (input_descriptor)
+ input_props = input_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB);
+ if (output_descriptor)
+ output_props = output_descriptor->props & (AV_CODEC_PROP_TEXT_SUB | AV_CODEC_PROP_BITMAP_SUB);
+ if (input_props && output_props && input_props != output_props) {
+ snprintf(error, error_len,
+ "Subtitle encoding currently only possible from text to text "
+ "or bitmap to bitmap");
+ return AVERROR_INVALIDDATA;
+ }
+ }
if ((ret = avcodec_open2(ost->enc_ctx, codec, &ost->encoder_opts)) < 0) {
if (ret == AVERROR_EXPERIMENTAL)
av_buffersink_set_frame_size(ost->filter->filter,
ost->enc_ctx->frame_size);
assert_avoptions(ost->encoder_opts);
- if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000)
+ if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000 &&
+ ost->enc_ctx->codec_id != AV_CODEC_ID_CODEC2 /* don't complain about 700 bit/s modes */)
av_log(NULL, AV_LOG_WARNING, "The bitrate parameter is set too low."
" It takes bits/s as argument, not kbits/s\n");
int i;
for (i = 0; i < ist->st->nb_side_data; i++) {
AVPacketSideData *sd = &ist->st->side_data[i];
- uint8_t *dst = av_stream_new_side_data(ost->st, sd->type, sd->size);
- if (!dst)
- return AVERROR(ENOMEM);
- memcpy(dst, sd->data, sd->size);
- if (ist->autorotate && sd->type == AV_PKT_DATA_DISPLAYMATRIX)
- av_display_rotation_set((uint32_t *)dst, 0);
+ if (sd->type != AV_PKT_DATA_CPB_PROPERTIES) {
+ uint8_t *dst = av_stream_new_side_data(ost->st, sd->type, sd->size);
+ if (!dst)
+ return AVERROR(ENOMEM);
+ memcpy(dst, sd->data, sd->size);
+ if (ist->autorotate && sd->type == AV_PKT_DATA_DISPLAYMATRIX)
+ av_display_rotation_set((uint32_t *)dst, 0);
+ }
}
}
ret = init_output_stream_streamcopy(ost);
if (ret < 0)
return ret;
-
- /*
- * FIXME: will the codec context used by the parser during streamcopy
- * This should go away with the new parser API.
- */
- ret = avcodec_parameters_to_context(ost->parser_avctx, ost->st->codecpar);
- if (ret < 0)
- return ret;
}
// parse user provided disposition, and update stream values
{ "hearing_impaired" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_HEARING_IMPAIRED }, .unit = "flags" },
{ "visual_impaired" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_VISUAL_IMPAIRED }, .unit = "flags" },
{ "clean_effects" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CLEAN_EFFECTS }, .unit = "flags" },
+ { "attached_pic" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_ATTACHED_PIC }, .unit = "flags" },
{ "captions" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CAPTIONS }, .unit = "flags" },
{ "descriptions" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DESCRIPTIONS }, .unit = "flags" },
+ { "dependent" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEPENDENT }, .unit = "flags" },
{ "metadata" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_METADATA }, .unit = "flags" },
{ NULL },
};
av_rescale_q(ost->st->cur_dts, ost->st->time_base,
AV_TIME_BASE_Q);
if (ost->st->cur_dts == AV_NOPTS_VALUE)
- av_log(NULL, AV_LOG_DEBUG, "cur_dts is invalid (this is harmless if it occurs once at the start per stream)\n");
+ av_log(NULL, AV_LOG_DEBUG,
+ "cur_dts is invalid st:%d (%d) [init:%d i_done:%d finish:%d] (this is harmless if it occurs once at the start per stream)\n",
+ ost->st->index, ost->st->id, ost->initialized, ost->inputs_done, ost->finished);
if (!ost->initialized && !ost->inputs_done)
return ost;
return NULL;
}
+static void free_input_thread(int i)
+{
+ InputFile *f = input_files[i];
+ AVPacket pkt;
+
+ if (!f || !f->in_thread_queue)
+ return;
+ av_thread_message_queue_set_err_send(f->in_thread_queue, AVERROR_EOF);
+ while (av_thread_message_queue_recv(f->in_thread_queue, &pkt, 0) >= 0)
+ av_packet_unref(&pkt);
+
+ pthread_join(f->thread, NULL);
+ f->joined = 1;
+ av_thread_message_queue_free(&f->in_thread_queue);
+}
+
static void free_input_threads(void)
{
int i;
- for (i = 0; i < nb_input_files; i++) {
- InputFile *f = input_files[i];
- AVPacket pkt;
+ for (i = 0; i < nb_input_files; i++)
+ free_input_thread(i);
+}
- if (!f || !f->in_thread_queue)
- continue;
- av_thread_message_queue_set_err_send(f->in_thread_queue, AVERROR_EOF);
- while (av_thread_message_queue_recv(f->in_thread_queue, &pkt, 0) >= 0)
- av_packet_unref(&pkt);
+static int init_input_thread(int i)
+{
+ int ret;
+ InputFile *f = input_files[i];
+
+ if (nb_input_files == 1)
+ return 0;
+
+ if (f->ctx->pb ? !f->ctx->pb->seekable :
+ strcmp(f->ctx->iformat->name, "lavfi"))
+ f->non_blocking = 1;
+ ret = av_thread_message_queue_alloc(&f->in_thread_queue,
+ f->thread_queue_size, sizeof(AVPacket));
+ if (ret < 0)
+ return ret;
- pthread_join(f->thread, NULL);
- f->joined = 1;
+ if ((ret = pthread_create(&f->thread, NULL, input_thread, f))) {
+ av_log(NULL, AV_LOG_ERROR, "pthread_create failed: %s. Try to increase `ulimit -v` or decrease `ulimit -s`.\n", strerror(ret));
av_thread_message_queue_free(&f->in_thread_queue);
+ return AVERROR(ret);
}
+
+ return 0;
}
static int init_input_threads(void)
{
int i, ret;
- if (nb_input_files == 1)
- return 0;
-
for (i = 0; i < nb_input_files; i++) {
- InputFile *f = input_files[i];
-
- if (f->ctx->pb ? !f->ctx->pb->seekable :
- strcmp(f->ctx->iformat->name, "lavfi"))
- f->non_blocking = 1;
- ret = av_thread_message_queue_alloc(&f->in_thread_queue,
- f->thread_queue_size, sizeof(AVPacket));
+ ret = init_input_thread(i);
if (ret < 0)
return ret;
-
- if ((ret = pthread_create(&f->thread, NULL, input_thread, f))) {
- av_log(NULL, AV_LOG_ERROR, "pthread_create failed: %s. Try to increase `ulimit -v` or decrease `ulimit -s`.\n", strerror(ret));
- av_thread_message_queue_free(&f->in_thread_queue);
- return AVERROR(ret);
- }
}
return 0;
}
// set duration to max(tmp, duration) in a proper time base and return duration's time_base
static AVRational duration_max(int64_t tmp, int64_t *duration, AVRational tmp_time_base,
- AVRational time_base)
+ AVRational time_base)
{
int ret;
int i, ret, has_audio = 0;
int64_t duration = 0;
- ret = av_seek_frame(is, -1, is->start_time, 0);
+ ret = avformat_seek_file(is, -1, INT64_MIN, is->start_time, is->start_time, 0);
if (ret < 0)
return ret;
ist = input_streams[ifile->ist_index + i];
avctx = ist->dec_ctx;
- // flush decoders
- if (ist->decoding_needed) {
- process_input_packet(ist, NULL, 1);
- avcodec_flush_buffers(avctx);
- }
-
/* duration is the length of the last frame in a stream
* when audio stream is present we don't care about
* last video frame length because it's not defined exactly */
ifile->time_base = ist->st->time_base;
/* the total duration of the stream, max_pts - min_pts is
* the duration of the stream without the last frame */
- duration += ist->max_pts - ist->min_pts;
+ if (ist->max_pts > ist->min_pts && ist->max_pts - (uint64_t)ist->min_pts < INT64_MAX - duration)
+ duration += ist->max_pts - ist->min_pts;
ifile->time_base = duration_max(duration, &ifile->duration, ist->st->time_base,
ifile->time_base);
}
AVFormatContext *is;
InputStream *ist;
AVPacket pkt;
- int ret, i, j;
+ int ret, thread_ret, i, j;
int64_t duration;
int64_t pkt_dts;
+ int disable_discontinuity_correction = copy_ts;
is = ifile->ctx;
ret = get_input_packet(ifile, &pkt);
return ret;
}
if (ret < 0 && ifile->loop) {
+ AVCodecContext *avctx;
+ for (i = 0; i < ifile->nb_streams; i++) {
+ ist = input_streams[ifile->ist_index + i];
+ avctx = ist->dec_ctx;
+ if (ist->decoding_needed) {
+ ret = process_input_packet(ist, NULL, 1);
+ if (ret>0)
+ return 0;
+ avcodec_flush_buffers(avctx);
+ }
+ }
+#if HAVE_THREADS
+ free_input_thread(file_index);
+#endif
ret = seek_to_start(ifile, is);
+#if HAVE_THREADS
+ thread_ret = init_input_thread(file_index);
+ if (thread_ret < 0)
+ return thread_ret;
+#endif
if (ret < 0)
av_log(NULL, AV_LOG_WARNING, "Seek to start failed.\n");
else
if (ist->discard)
goto discard_packet;
- if (exit_on_error && (pkt.flags & AV_PKT_FLAG_CORRUPT)) {
- av_log(NULL, AV_LOG_FATAL, "%s: corrupt input packet in stream %d\n", is->url, pkt.stream_index);
- exit_program(1);
+ if (pkt.flags & AV_PKT_FLAG_CORRUPT) {
+ av_log(NULL, exit_on_error ? AV_LOG_FATAL : AV_LOG_WARNING,
+ "%s: corrupt input packet in stream %d\n", is->url, pkt.stream_index);
+ if (exit_on_error)
+ exit_program(1);
}
if (debug_ts) {
pkt.dts += duration;
pkt_dts = av_rescale_q_rnd(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
+
+ if (copy_ts && pkt_dts != AV_NOPTS_VALUE && ist->next_dts != AV_NOPTS_VALUE &&
+ (is->iformat->flags & AVFMT_TS_DISCONT) && ist->st->pts_wrap_bits < 60) {
+ int64_t wrap_dts = av_rescale_q_rnd(pkt.dts + (1LL<<ist->st->pts_wrap_bits),
+ ist->st->time_base, AV_TIME_BASE_Q,
+ AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
+ if (FFABS(wrap_dts - ist->next_dts) < FFABS(pkt_dts - ist->next_dts)/10)
+ disable_discontinuity_correction = 0;
+ }
+
if ((ist->dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO ||
ist->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) &&
pkt_dts != AV_NOPTS_VALUE && ist->next_dts != AV_NOPTS_VALUE &&
- !copy_ts) {
+ !disable_discontinuity_correction) {
int64_t delta = pkt_dts - ist->next_dts;
if (is->iformat->flags & AVFMT_TS_DISCONT) {
if (delta < -1LL*dts_delta_threshold*AV_TIME_BASE ||
pkt_dts + AV_TIME_BASE/10 < FFMAX(ist->pts, ist->dts)) {
ifile->ts_offset -= delta;
av_log(NULL, AV_LOG_DEBUG,
- "timestamp discontinuity %"PRId64", new offset= %"PRId64"\n",
+ "timestamp discontinuity for stream #%d:%d "
+ "(id=%d, type=%s): %"PRId64", new offset= %"PRId64"\n",
+ ist->file_index, ist->st->index, ist->st->id,
+ av_get_media_type_string(ist->dec_ctx->codec_type),
delta, ifile->ts_offset);
pkt.dts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base);
if (pkt.pts != AV_NOPTS_VALUE)
ret = transcode_step();
if (ret < 0 && ret != AVERROR_EOF) {
- char errbuf[128];
- av_strerror(ret, errbuf, sizeof(errbuf));
-
- av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", errbuf);
+ av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret));
break;
}
return ret;
}
-
-static int64_t getutime(void)
+static BenchmarkTimeStamps get_benchmark_time_stamps(void)
{
+ BenchmarkTimeStamps time_stamps = { av_gettime_relative() };
#if HAVE_GETRUSAGE
struct rusage rusage;
getrusage(RUSAGE_SELF, &rusage);
- return (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec;
+ time_stamps.user_usec =
+ (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec;
+ time_stamps.sys_usec =
+ (rusage.ru_stime.tv_sec * 1000000LL) + rusage.ru_stime.tv_usec;
#elif HAVE_GETPROCESSTIMES
HANDLE proc;
FILETIME c, e, k, u;
proc = GetCurrentProcess();
GetProcessTimes(proc, &c, &e, &k, &u);
- return ((int64_t) u.dwHighDateTime << 32 | u.dwLowDateTime) / 10;
+ time_stamps.user_usec =
+ ((int64_t)u.dwHighDateTime << 32 | u.dwLowDateTime) / 10;
+ time_stamps.sys_usec =
+ ((int64_t)k.dwHighDateTime << 32 | k.dwLowDateTime) / 10;
#else
- return av_gettime_relative();
+ time_stamps.user_usec = time_stamps.sys_usec = 0;
#endif
+ return time_stamps;
}
static int64_t getmaxrss(void)
int main(int argc, char **argv)
{
int i, ret;
- int64_t ti;
+ BenchmarkTimeStamps ti;
init_dynload();
argv++;
}
- avcodec_register_all();
#if CONFIG_AVDEVICE
avdevice_register_all();
#endif
- avfilter_register_all();
- av_register_all();
avformat_network_init();
show_banner(argc, argv, options);
exit_program(1);
}
-// if (nb_input_files == 0) {
-// av_log(NULL, AV_LOG_FATAL, "At least one input file must be specified\n");
-// exit_program(1);
-// }
-
for (i = 0; i < nb_output_files; i++) {
if (strcmp(output_files[i]->ctx->oformat->name, "rtp"))
want_sdp = 0;
}
- current_time = ti = getutime();
+ current_time = ti = get_benchmark_time_stamps();
if (transcode() < 0)
exit_program(1);
- ti = getutime() - ti;
if (do_benchmark) {
- av_log(NULL, AV_LOG_INFO, "bench: utime=%0.3fs\n", ti / 1000000.0);
+ int64_t utime, stime, rtime;
+ current_time = get_benchmark_time_stamps();
+ utime = current_time.user_usec - ti.user_usec;
+ stime = current_time.sys_usec - ti.sys_usec;
+ rtime = current_time.real_usec - ti.real_usec;
+ av_log(NULL, AV_LOG_INFO,
+ "bench: utime=%0.3fs stime=%0.3fs rtime=%0.3fs\n",
+ utime / 1000000.0, stime / 1000000.0, rtime / 1000000.0);
}
av_log(NULL, AV_LOG_DEBUG, "%"PRIu64" frames successfully decoded, %"PRIu64" decoding errors\n",
decode_error_stat[0], decode_error_stat[1]);