Newer
Older
for (i = 0; i < nb_frames; i++) {
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
if (s->oformat->flags & AVFMT_RAWPICTURE &&
enc->codec->id == CODEC_ID_RAWVIDEO) {
/* raw pictures are written as AVPicture structure to
avoid any copies. We support temporarily the older
method. */
enc->coded_frame->interlaced_frame = in_picture->interlaced_frame;
enc->coded_frame->top_field_first = in_picture->top_field_first;
pkt.data = (uint8_t *)in_picture;
pkt.size = sizeof(AVPicture);
pkt.pts = av_rescale_q(ost->sync_opts, enc->time_base, ost->st->time_base);
pkt.flags |= AV_PKT_FLAG_KEY;
write_frame(s, &pkt, ost);
} else {
Michael Niedermayer
committed
/* better than nothing: use input picture interlaced
settings */
big_picture.interlaced_frame = in_picture->interlaced_frame;
if (ost->st->codec->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME)) {
if (ost->top_field_first == -1)
big_picture.top_field_first = in_picture->top_field_first;
else
big_picture.top_field_first = !!ost->top_field_first;
/* handles same_quant here. This is not correct because it may
if (!enc->me_threshold)
Michael Niedermayer
committed
big_picture.pict_type = 0;
big_picture.pts = ost->sync_opts;
if (ost->forced_kf_index < ost->forced_kf_count &&
big_picture.pts >= ost->forced_kf_pts[ost->forced_kf_index]) {
big_picture.pict_type = AV_PICTURE_TYPE_I;
ost->forced_kf_index++;
}
ret = avcodec_encode_video2(enc, &pkt, &big_picture, &got_packet);
update_benchmark("encode_video %d.%d", ost->file_index, ost->index);
av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n");
if (pkt.pts == AV_NOPTS_VALUE && !(enc->codec->capabilities & CODEC_CAP_DELAY))
pkt.pts = ost->sync_opts;
if (pkt.pts != AV_NOPTS_VALUE)
pkt.pts = av_rescale_q(pkt.pts, enc->time_base, ost->st->time_base);
if (pkt.dts != AV_NOPTS_VALUE)
pkt.dts = av_rescale_q(pkt.dts, enc->time_base, ost->st->time_base);
if (debug_ts) {
av_log(NULL, AV_LOG_INFO, "encoder -> type:video "
"pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s\n",
av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ost->st->time_base),
av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ost->st->time_base));
}
write_frame(s, &pkt, ost);
frame_size = pkt.size;
video_size += pkt.size;
/* if two pass, output log */
if (ost->logfile && enc->stats_out) {
fprintf(ost->logfile, "%s", enc->stats_out);
}
/*
* 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.
*/
Fabrice Bellard
committed
ost->frame_number++;
if (vstats_filename && frame_size)
do_video_stats(output_files[ost->file_index]->ctx, ost, frame_size);
/* check for new output on any of the filtergraphs */
static int poll_filters(void)
{
AVFilterBufferRef *picref;
AVFrame *filtered_frame = NULL;
int i, ret, ret_all;
unsigned nb_success, nb_eof;
while (1) {
/* Reap all buffers present in the buffer sinks */
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = output_streams[i];
OutputFile *of = output_files[ost->file_index];
if (!ost->filter || ost->is_past_recording_time)
continue;
if (!ost->filtered_frame && !(ost->filtered_frame = avcodec_alloc_frame())) {
return AVERROR(ENOMEM);
} else
avcodec_get_frame_defaults(ost->filtered_frame);
filtered_frame = ost->filtered_frame;
while (1) {
AVRational ist_pts_tb = ost->filter->filter->inputs[0]->time_base;
ret = av_buffersink_get_buffer_ref(ost->filter->filter, &picref,
AV_BUFFERSINK_FLAG_NO_REQUEST);
if (ret < 0) {
if (ret != AVERROR(EAGAIN)) {
char buf[256];
av_strerror(ret, buf, sizeof(buf));
av_log(NULL, AV_LOG_WARNING,
"Error in av_buffersink_get_buffer_ref(): %s\n", buf);
}
break;
}
filtered_frame->pts = av_rescale_q(picref->pts, ist_pts_tb, AV_TIME_BASE_Q);
//if (ost->source_index >= 0)
// *filtered_frame= *input_streams[ost->source_index]->decoded_frame; //for me_threshold
if (of->start_time && filtered_frame->pts < of->start_time)
return 0;
switch (ost->filter->filter->inputs[0]->type) {
case AVMEDIA_TYPE_VIDEO:
avfilter_fill_frame_from_video_buffer_ref(filtered_frame, picref);
if (!ost->frame_aspect_ratio)
ost->st->codec->sample_aspect_ratio = picref->video->sample_aspect_ratio;
do_video_out(of->ctx, ost, filtered_frame,
same_quant ? ost->last_quality :
ost->st->codec->global_quality);
break;
default:
// TODO support audio/subtitle filters
av_assert0(0);
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
/* Request frames through all the graphs */
ret_all = nb_success = nb_eof = 0;
for (i = 0; i < nb_filtergraphs; i++) {
ret = avfilter_graph_request_oldest(filtergraphs[i]->graph);
if (!ret) {
nb_success++;
} else if (ret == AVERROR_EOF) {
nb_eof++;
} else if (ret != AVERROR(EAGAIN)) {
char buf[256];
av_strerror(ret, buf, sizeof(buf));
av_log(NULL, AV_LOG_WARNING,
"Error in request_frame(): %s\n", buf);
ret_all = ret;
}
}
if (!nb_success)
break;
/* Try again if anything succeeded */
}
return nb_eof == nb_filtergraphs ? AVERROR_EOF : ret_all;
static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time)
Fabrice Bellard
committed
{
char buf[1024];
AVFormatContext *oc;
Fabrice Bellard
committed
AVCodecContext *enc;
int frame_number, vid, i;
Baptiste Coudurier
committed
double bitrate;
int64_t pts = INT64_MAX;
static int qp_histogram[52];
int hours, mins, secs, us;
if (!print_stats && !is_last_report)
return;
Fabrice Bellard
committed
if (!is_last_report) {
if (last_time == -1) {
last_time = cur_time;
return;
Fabrice Bellard
committed
if ((cur_time - last_time) < 500000)
return;
last_time = cur_time;
}
oc = output_files[0]->ctx;
Fabrice Bellard
committed
if (total_size < 0) { // FIXME improve avio_size() so it works with non seekable output too
total_size = avio_tell(oc->pb);
if (total_size < 0)
total_size = 0;
}
Fabrice Bellard
committed
buf[0] = '\0';
vid = 0;
for (i = 0; i < nb_output_streams; i++) {
ost = output_streams[i];
Michael Niedermayer
committed
enc = ost->st->codec;
if (!ost->stream_copy && enc->coded_frame)
q = enc->coded_frame->quality / (float)FF_QP2LAMBDA;
if (vid && enc->codec_type == AVMEDIA_TYPE_VIDEO) {
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "q=%2.1f ", q);
}
if (!vid && enc->codec_type == AVMEDIA_TYPE_VIDEO) {
float fps, t = (cur_time-timer_start) / 1000000.0;
Fabrice Bellard
committed
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 ",
frame_number, fps < 9.95, fps, q);
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "L");
if (qp >= 0 && qp < FF_ARRAY_ELEMS(qp_histogram))
for (j = 0; j < 32; j++)
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%X", (int)lrintf(log(qp_histogram[j] + 1) / log(2)));
if (enc->flags&CODEC_FLAG_PSNR) {
Michael Niedermayer
committed
int j;
double error, error_sum = 0;
double scale, scale_sum = 0;
char type[3] = { 'Y','U','V' };
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "PSNR=");
for (j = 0; j < 3; j++) {
if (is_last_report) {
error = enc->error[j];
scale = enc->width * enc->height * 255.0 * 255.0 * frame_number;
} else {
error = enc->coded_frame->error[j];
scale = enc->width * enc->height * 255.0 * 255.0;
Michael Niedermayer
committed
}
if (j)
scale /= 4;
Michael Niedermayer
committed
error_sum += error;
scale_sum += scale;
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%c:%2.2f ", type[j], psnr(error / scale));
Michael Niedermayer
committed
}
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "*:%2.2f ", psnr(error_sum / scale_sum));
Michael Niedermayer
committed
}
Fabrice Bellard
committed
vid = 1;
}
/* compute min output value */
Baptiste Coudurier
committed
pts = FFMIN(pts, av_rescale_q(ost->st->pts.val,
ost->st->time_base, AV_TIME_BASE_Q));
Fabrice Bellard
committed
}
secs = pts / AV_TIME_BASE;
us = pts % AV_TIME_BASE;
mins = secs / 60;
secs %= 60;
hours = mins / 60;
mins %= 60;
bitrate = pts ? total_size * 8 / (pts / 1000.0) : 0;
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
"size=%8.0fkB time=", total_size / 1024.0);
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
"%02d:%02d:%02d.%02d ", hours, mins, secs,
(100 * us) / AV_TIME_BASE);
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
"bitrate=%6.1fkbits/s", bitrate);
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_log(NULL, AV_LOG_INFO, "%s \r", buf);
if (is_last_report) {
int64_t raw= audio_size + video_size + extra_size;
av_log(NULL, AV_LOG_INFO, "\n");
av_log(NULL, AV_LOG_INFO, "video:%1.0fkB audio:%1.0fkB global headers:%1.0fkB muxing overhead %f%%\n",
video_size / 1024.0,
audio_size / 1024.0,
extra_size / 1024.0,
100.0 * (total_size - raw) / raw
if(video_size + audio_size + extra_size == 0){
av_log(NULL, AV_LOG_WARNING, "Output file is empty, nothing was encoded (check -ss / -t / -frames parameters if used)\n");
}
static void flush_encoders(void)
{
int i, ret;
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = output_streams[i];
AVCodecContext *enc = ost->st->codec;
AVFormatContext *os = output_files[ost->file_index]->ctx;
int stop_encoding = 0;
if (!ost->encoding_needed)
continue;
if (ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <= 1)
if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && (os->oformat->flags & AVFMT_RAWPICTURE) && enc->codec->id == CODEC_ID_RAWVIDEO)
continue;
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
switch (ost->st->codec->codec_type) {
case AVMEDIA_TYPE_AUDIO:
fifo_bytes = av_fifo_size(ost->fifo);
if (fifo_bytes > 0) {
/* encode any samples remaining in fifo */
int frame_bytes = fifo_bytes;
av_fifo_generic_read(ost->fifo, audio_buf, fifo_bytes, NULL);
encode_audio_frame(os, ost, audio_buf, frame_bytes);
} else {
/* flush encoder with NULL frames until it is done
returning packets */
if (encode_audio_frame(os, ost, NULL, 0) == 0) {
stop_encoding = 1;
break;
Fabrice Bellard
committed
}
}
break;
case AVMEDIA_TYPE_VIDEO:
ret = avcodec_encode_video2(enc, &pkt, NULL, &got_packet);
update_benchmark("encode_video %d.%d", ost->file_index, ost->index);
if (ret < 0) {
av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n");
exit_program(1);
}
video_size += pkt.size;
if (ost->logfile && enc->stats_out) {
fprintf(ost->logfile, "%s", enc->stats_out);
}
stop_encoding = 1;
break;
if (pkt.pts != AV_NOPTS_VALUE)
pkt.pts = av_rescale_q(pkt.pts, enc->time_base, ost->st->time_base);
if (pkt.dts != AV_NOPTS_VALUE)
pkt.dts = av_rescale_q(pkt.dts, enc->time_base, ost->st->time_base);
write_frame(os, &pkt, ost);
break;
default:
}
}
}
/*
* Check whether a packet from ist should be written into ost at this time
*/
static int check_output_constraints(InputStream *ist, OutputStream *ost)
{
OutputFile *of = output_files[ost->file_index];
int ist_index = input_files[ist->file_index]->ist_index + ist->st->index;
if (ost->source_index != ist_index)
return 0;
if (of->start_time && ist->pts < of->start_time)
return 0;
if (of->recording_time != INT64_MAX &&
av_compare_ts(ist->pts, AV_TIME_BASE_Q, of->recording_time + of->start_time,
(AVRational){ 1, 1000000 }) >= 0) {
ost->is_past_recording_time = 1;
return 0;
}
return 1;
}
static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *pkt)
{
OutputFile *of = output_files[ost->file_index];
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
int64_t ost_tb_start_time = av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base);
AVPicture pict;
AVPacket opkt;
av_init_packet(&opkt);
if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) &&
!ost->copy_initial_nonkeyframes)
return;
/* force the input stream PTS */
if (ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
audio_size += pkt->size;
else if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
video_size += pkt->size;
ost->sync_opts++;
}
if (pkt->pts != AV_NOPTS_VALUE)
opkt.pts = av_rescale_q(pkt->pts, ist->st->time_base, ost->st->time_base) - ost_tb_start_time;
else
opkt.pts = AV_NOPTS_VALUE;
if (pkt->dts == AV_NOPTS_VALUE)
opkt.dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ost->st->time_base);
else
opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base);
opkt.dts -= ost_tb_start_time;
opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base);
opkt.flags = pkt->flags;
// FIXME remove the following 2 lines they shall be replaced by the bitstream filters
if ( ost->st->codec->codec_id != CODEC_ID_H264
&& ost->st->codec->codec_id != CODEC_ID_MPEG1VIDEO
&& ost->st->codec->codec_id != CODEC_ID_MPEG2VIDEO
&& ost->st->codec->codec_id != CODEC_ID_VC1
) {
if (av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, pkt->data, pkt->size, pkt->flags & AV_PKT_FLAG_KEY))
opkt.destruct = av_destruct_packet;
} else {
opkt.data = pkt->data;
opkt.size = pkt->size;
}
if (of->ctx->oformat->flags & AVFMT_RAWPICTURE) {
/* store AVPicture in AVPacket, as expected by the output format */
avpicture_fill(&pict, opkt.data, ost->st->codec->pix_fmt, ost->st->codec->width, ost->st->codec->height);
opkt.data = (uint8_t *)&pict;
opkt.size = sizeof(AVPicture);
opkt.flags |= AV_PKT_FLAG_KEY;
}
write_frame(of->ctx, &opkt, ost);
ost->st->codec->frame_number++;
av_free_packet(&opkt);
}
static void rate_emu_sleep(InputStream *ist)
{
if (input_files[ist->file_index]->rate_emu) {
int64_t pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE);
int64_t now = av_gettime() - ist->start;
if (pts > now)
usleep(pts - now);
}
}
static int transcode_audio(InputStream *ist, AVPacket *pkt, int *got_output)
{
AVFrame *decoded_frame;
AVCodecContext *avctx = ist->st->codec;
int bps = av_get_bytes_per_sample(ist->st->codec->sample_fmt);
int i, ret;
if (!ist->decoded_frame && !(ist->decoded_frame = avcodec_alloc_frame()))
return AVERROR(ENOMEM);
else
avcodec_get_frame_defaults(ist->decoded_frame);
decoded_frame = ist->decoded_frame;
ret = avcodec_decode_audio4(avctx, decoded_frame, got_output, pkt);
update_benchmark("decode_audio %d.%d", ist->file_index, ist->st->index);
if (avctx->sample_rate <= 0) {
av_log(avctx, AV_LOG_ERROR, "Sample rate %d invalid\n", avctx->sample_rate);
return AVERROR_INVALIDDATA;
}
if (!*got_output) {
/* no audio frame */
/* if the decoder provides a pts, use it instead of the last packet pts.
the decoder could be delaying output by a packet or more. */
if (decoded_frame->pts != AV_NOPTS_VALUE)
ist->dts = ist->next_dts = ist->pts = ist->next_pts = decoded_frame->pts;
/* 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;
// preprocess audio (volume)
if (audio_volume != 256) {
int decoded_data_size = decoded_frame->nb_samples * avctx->channels * bps;
void *samples = decoded_frame->data[0];
switch (avctx->sample_fmt) {
case AV_SAMPLE_FMT_U8:
{
uint8_t *volp = samples;
for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) {
int v = (((*volp - 128) * audio_volume + 128) >> 8) + 128;
*volp++ = av_clip_uint8(v);
case AV_SAMPLE_FMT_S16:
{
int16_t *volp = samples;
for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) {
int v = ((*volp) * audio_volume + 128) >> 8;
*volp++ = av_clip_int16(v);
}
case AV_SAMPLE_FMT_S32:
{
int32_t *volp = samples;
for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) {
int64_t v = (((int64_t)*volp * audio_volume + 128) >> 8);
*volp++ = av_clipl_int32(v);
}
break;
}
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
case AV_SAMPLE_FMT_FLT:
{
float *volp = samples;
float scale = audio_volume / 256.f;
for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) {
*volp++ *= scale;
}
break;
}
case AV_SAMPLE_FMT_DBL:
{
double *volp = samples;
double scale = audio_volume / 256.;
for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) {
*volp++ *= scale;
}
break;
}
default:
av_log(NULL, AV_LOG_FATAL,
"Audio volume adjustment on sample format %s is not supported.\n",
av_get_sample_fmt_name(ist->st->codec->sample_fmt));
exit_program(1);
}
}
rate_emu_sleep(ist);
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = output_streams[i];
if (!check_output_constraints(ist, ost) || !ost->encoding_needed)
continue;
do_audio_out(output_files[ost->file_index]->ctx, ost, ist, decoded_frame);
Michael Niedermayer
committed
static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_t *pkt_pts)
AVFrame *decoded_frame;
void *buffer_to_free = NULL;
int i, ret = 0, resample_changed;
Michael Niedermayer
committed
AVRational *frame_sample_aspect;
if (!ist->decoded_frame && !(ist->decoded_frame = avcodec_alloc_frame()))
return AVERROR(ENOMEM);
else
avcodec_get_frame_defaults(ist->decoded_frame);
decoded_frame = ist->decoded_frame;
Michael Niedermayer
committed
pkt->dts = ist->dts;
*pkt_pts = AV_NOPTS_VALUE;
ret = avcodec_decode_video2(ist->st->codec,
decoded_frame, got_output, pkt);
update_benchmark("decode_video %d.%d", ist->file_index, ist->st->index);
quality = same_quant ? decoded_frame->quality : 0;
if (!*got_output) {
/* no picture yet */
if (!pkt->size)
for (i = 0; i < ist->nb_filters; i++)
av_buffersrc_add_ref(ist->filters[i]->filter, NULL, 0);
best_effort_timestamp= av_frame_get_best_effort_timestamp(decoded_frame);
if(best_effort_timestamp != AV_NOPTS_VALUE)
ist->next_pts = ist->pts = decoded_frame->pts = best_effort_timestamp;
pre_process_video_frame(ist, (AVPicture *)decoded_frame, &buffer_to_free);
if (ist->st->sample_aspect_ratio.num)
decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio;
resample_changed = ist->resample_width != decoded_frame->width ||
ist->resample_height != decoded_frame->height ||
ist->resample_pix_fmt != decoded_frame->format;
if (resample_changed) {
av_log(NULL, AV_LOG_INFO,
"Input stream #%d:%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n",
ist->file_index, ist->st->index,
ist->resample_width, ist->resample_height, av_get_pix_fmt_name(ist->resample_pix_fmt),
decoded_frame->width, decoded_frame->height, av_get_pix_fmt_name(decoded_frame->format));
ist->resample_width = decoded_frame->width;
ist->resample_height = decoded_frame->height;
ist->resample_pix_fmt = decoded_frame->format;
for (i = 0; i < nb_filtergraphs; i++)
if (ist_in_filtergraph(filtergraphs[i], ist) &&
configure_filtergraph(filtergraphs[i]) < 0) {
av_log(NULL, AV_LOG_FATAL, "Error reinitializing filters!\n");
exit_program(1);
frame_sample_aspect= av_opt_ptr(avcodec_get_frame_class(), decoded_frame, "sample_aspect_ratio");
for (i = 0; i < ist->nb_filters; i++) {
int changed = ist->st->codec->width != ist->filters[i]->filter->outputs[0]->w
|| ist->st->codec->height != ist->filters[i]->filter->outputs[0]->h
|| ist->st->codec->pix_fmt != ist->filters[i]->filter->outputs[0]->format;
// XXX what an ugly hack
if (ist->filters[i]->graph->nb_outputs == 1)
ist->filters[i]->graph->outputs[0]->ost->last_quality = quality;
if (!frame_sample_aspect->num)
*frame_sample_aspect = ist->st->sample_aspect_ratio;
if (ist->dr1 && decoded_frame->type==FF_BUFFER_TYPE_USER && !changed) {
FrameBuffer *buf = decoded_frame->opaque;
AVFilterBufferRef *fb = avfilter_get_video_buffer_ref_from_arrays(
decoded_frame->data, decoded_frame->linesize,
AV_PERM_READ | AV_PERM_PRESERVE,
ist->st->codec->width, ist->st->codec->height,
ist->st->codec->pix_fmt);
avfilter_copy_frame_props(fb, decoded_frame);
fb->buf->priv = buf;
fb->buf->free = filter_release_buffer;
av_assert0(buf->refcount>0);
av_buffersrc_add_ref(ist->filters[i]->filter, fb,
AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT |
AV_BUFFERSRC_FLAG_NO_COPY);
if(av_buffersrc_add_frame(ist->filters[i]->filter, decoded_frame, 0)<0) {
av_log(NULL, AV_LOG_FATAL, "Failed to inject frame into filter network\n");
exit_program(1);
av_free(buffer_to_free);
return ret;
Fabrice Bellard
committed
}
static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output)
{
AVSubtitle subtitle;
int i, ret = avcodec_decode_subtitle2(ist->st->codec,
&subtitle, got_output, pkt);
if (ret < 0)
return ret;
if (!*got_output)
rate_emu_sleep(ist);
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = output_streams[i];
if (!check_output_constraints(ist, ost) || !ost->encoding_needed)
continue;
do_subtitle_out(output_files[ost->file_index]->ctx, ost, ist, &subtitle, pkt->pts);
}
avsubtitle_free(&subtitle);
}
Fabrice Bellard
committed
/* pkt = NULL means EOF (needed to flush decoder buffers) */
static int output_packet(InputStream *ist, const AVPacket *pkt)
Fabrice Bellard
committed
{
int got_output;
int64_t pkt_pts = AV_NOPTS_VALUE;
Michael Niedermayer
committed
if (!ist->saw_first_ts) {
ist->dts = ist->st->avg_frame_rate.num ? - ist->st->codec->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0;
ist->pts = 0;
if (pkt != NULL && pkt->pts != AV_NOPTS_VALUE && !ist->decoding_needed) {
ist->dts += av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q);
ist->pts = ist->dts; //unused but better to set it to a value thats not totally wrong
}
ist->saw_first_ts = 1;
}
if (ist->next_dts == AV_NOPTS_VALUE)
ist->next_dts = ist->dts;
if (ist->next_pts == AV_NOPTS_VALUE)
ist->next_pts = ist->pts;
Michael Niedermayer
committed
Fabrice Bellard
committed
if (pkt == NULL) {
/* EOF handling */
av_init_packet(&avpkt);
avpkt.data = NULL;
avpkt.size = 0;
Fabrice Bellard
committed
goto handle_eof;
} else {
avpkt = *pkt;
Fabrice Bellard
committed
}
if (pkt->dts != AV_NOPTS_VALUE) {
ist->next_dts = ist->dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
if (ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO || !ist->decoding_needed)
ist->next_pts = ist->pts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
}
if(pkt->pts != AV_NOPTS_VALUE)
pkt_pts = av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q);
// while we have more to decode or while the decoder did output something on EOF
while (ist->decoding_needed && (avpkt.size > 0 || (!pkt && got_output))) {
int duration;
Fabrice Bellard
committed
handle_eof:
Michael Niedermayer
committed
ist->pts = ist->next_pts;
ist->dts = ist->next_dts;
if (avpkt.size && avpkt.size != pkt->size) {
av_log(NULL, ist->showed_multi_packet_warning ? AV_LOG_VERBOSE : AV_LOG_WARNING,
"Multiple frames in a packet from stream %d\n", pkt->stream_index);
ist->showed_multi_packet_warning = 1;
}
switch (ist->st->codec->codec_type) {
case AVMEDIA_TYPE_AUDIO:
ret = transcode_audio (ist, &avpkt, &got_output);
break;
case AVMEDIA_TYPE_VIDEO:
Michael Niedermayer
committed
ret = transcode_video (ist, &avpkt, &got_output, &pkt_pts);
if (avpkt.duration) {
duration = av_rescale_q(avpkt.duration, ist->st->time_base, AV_TIME_BASE_Q);
} else if(ist->st->codec->time_base.num != 0 && ist->st->codec->time_base.den != 0) {
int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame;
duration = ((int64_t)AV_TIME_BASE *
ist->st->codec->time_base.num * ticks) /
ist->st->codec->time_base.den;
} else
duration = 0;
if(ist->dts != AV_NOPTS_VALUE && duration) {
ist->next_dts += duration;
}else
ist->next_dts = AV_NOPTS_VALUE;
if (got_output)
ist->next_pts += duration; //FIXME the duration is not correct in some cases
break;
case AVMEDIA_TYPE_SUBTITLE:
ret = transcode_subtitles(ist, &avpkt, &got_output);
default:
return -1;
}
Fabrice Bellard
committed
if (ret < 0)
return ret;
avpkt.dts=
avpkt.pts= AV_NOPTS_VALUE;
// touch data and size only if not EOF
if (pkt) {
if(ist->st->codec->codec_type != AVMEDIA_TYPE_AUDIO)
ret = avpkt.size;
avpkt.data += ret;
avpkt.size -= ret;
}
}
/* handle stream copy */
if (!ist->decoding_needed) {
rate_emu_sleep(ist);
ist->dts = ist->next_dts;
switch (ist->st->codec->codec_type) {
case AVMEDIA_TYPE_AUDIO:
ist->next_dts += ((int64_t)AV_TIME_BASE * ist->st->codec->frame_size) /
ist->st->codec->sample_rate;
break;
case AVMEDIA_TYPE_VIDEO:
Michael Niedermayer
committed
if (pkt->duration) {
ist->next_dts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q);
Michael Niedermayer
committed
} else if(ist->st->codec->time_base.num != 0) {
int ticks= ist->st->parser ? ist->st->parser->repeat_pict + 1 : ist->st->codec->ticks_per_frame;
ist->next_dts += ((int64_t)AV_TIME_BASE *
ist->st->codec->time_base.num * ticks) /
ist->st->codec->time_base.den;
}
ist->pts = ist->dts;
ist->next_pts = ist->next_dts;
for (i = 0; pkt && i < nb_output_streams; i++) {
OutputStream *ost = output_streams[i];
if (!check_output_constraints(ist, ost) || ost->encoding_needed)
continue;
do_streamcopy(ist, ost, pkt);
}
Fabrice Bellard
committed
return 0;
}
static void print_sdp(void)
{
char sdp[2048];
Anton Khirnov
committed
int i;
AVFormatContext **avc = av_malloc(sizeof(*avc) * nb_output_files);
Anton Khirnov
committed
if (!avc)
exit_program(1);
for (i = 0; i < nb_output_files; i++)
avc[i] = output_files[i]->ctx;
av_sdp_create(avc, nb_output_files, sdp, sizeof(sdp));
printf("SDP:\n%s\n", sdp);
Anton Khirnov
committed
av_freep(&avc);
}
Fabrice Bellard
committed
static int init_input_stream(int ist_index, char *error, int error_len)
InputStream *ist = input_streams[ist_index];
if (ist->decoding_needed) {
AVCodec *codec = ist->dec;
if (!codec) {
snprintf(error, error_len, "Decoder (codec %s) not found for input stream #%d:%d",
avcodec_get_name(ist->st->codec->codec_id), ist->file_index, ist->st->index);
return AVERROR(EINVAL);
}
ist->dr1 = (codec->capabilities & CODEC_CAP_DR1) && !do_deinterlace;
Michael Niedermayer
committed
if (codec->type == AVMEDIA_TYPE_VIDEO && ist->dr1) {
ist->st->codec->get_buffer = codec_get_buffer;
ist->st->codec->release_buffer = codec_release_buffer;
ist->st->codec->opaque = ist;
}
Michael Niedermayer
committed
if (!av_dict_get(ist->opts, "threads", NULL, 0))
av_dict_set(&ist->opts, "threads", "auto", 0);
if (avcodec_open2(ist->st->codec, codec, &ist->opts) < 0) {
snprintf(error, error_len, "Error while opening decoder for input stream #%d:%d",
ist->file_index, ist->st->index);
return AVERROR(EINVAL);
}
assert_codec_experimental(ist->st->codec, 0);
assert_avoptions(ist->opts);
if (ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = output_streams[i];
if (ost->source_index == ist_index) {
if (!ist->st->codec->channel_layout || !ost->st->codec->channel_layout)
get_default_channel_layouts(ost, ist);
break;
}
}
}
}
ist->next_pts = AV_NOPTS_VALUE;
ist->is_start = 1;
return 0;
}
static InputStream *get_input_stream(OutputStream *ost)
{
if (ost->source_index >= 0)
return input_streams[ost->source_index];
if (ost->filter) {
FilterGraph *fg = ost->filter->graph;
int i;
for (i = 0; i < fg->nb_inputs; i++)
if (fg->inputs[i]->ist->st->codec->codec_type == ost->st->codec->codec_type)
return fg->inputs[i]->ist;
}
return NULL;
}
static int transcode_init(void)
int ret = 0, i, j, k;
OutputStream *ost;
char error[1024];
int want_sdp = 1;
/* init framerate emulation */
for (i = 0; i < nb_input_files; i++) {
InputFile *ifile = input_files[i];
if (ifile->rate_emu)
for (j = 0; j < ifile->nb_streams; j++)
input_streams[j + ifile->ist_index]->start = av_gettime();
for (i = 0; i < nb_output_files; i++) {
oc = output_files[i]->ctx;
if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) {
av_dump_format(oc, i, oc->filename, 1);
av_log(NULL, AV_LOG_ERROR, "Output file #%d does not contain any stream\n", i);
return AVERROR(EINVAL);
/* init complex filtergraphs */
for (i = 0; i < nb_filtergraphs; i++)
if ((ret = avfilter_graph_config(filtergraphs[i]->graph, NULL)) < 0)
return ret;
/* for each output stream, we compute the right encoding parameters */
for (i = 0; i < nb_output_streams; i++) {
ost = output_streams[i];
oc = output_files[ost->file_index]->ctx;
ist = get_input_stream(ost);
if (ost->attachment_filename)
continue;
codec = ost->st->codec;
if (ist) {
icodec = ist->st->codec;
ost->st->disposition = ist->st->disposition;
codec->bits_per_raw_sample = icodec->bits_per_raw_sample;