Newer
Older
audio_buf_size = (allocated_for_size + isize * dec->channels - 1) / (isize * dec->channels);
audio_buf_size = (audio_buf_size * enc->sample_rate + dec->sample_rate) / dec->sample_rate;
audio_buf_size = audio_buf_size * 2 + 10000; // safety factors for the deprecated resampling API
audio_buf_size = FFMAX(audio_buf_size, enc->frame_size);
audio_buf_size *= osize * enc->channels;
av_log(NULL, AV_LOG_FATAL, "Buffer sizes too large\n");
exit_program(1);
}
av_fast_malloc(&audio_buf, &allocated_audio_buf_size, audio_buf_size);
av_log(NULL, AV_LOG_FATAL, "Out of memory in do_audio_out\n");
exit_program(1);
}
if (enc->channels != dec->channels || enc->sample_rate != dec->sample_rate)
ost->audio_resample = 1;
resample_changed = ost->resample_sample_fmt != dec->sample_fmt ||
ost->resample_channels != dec->channels ||
ost->resample_sample_rate != dec->sample_rate;
if ((ost->audio_resample && !ost->resample) || resample_changed) {
if (resample_changed) {
av_log(NULL, AV_LOG_INFO, "Input stream #%d:%d frame changed from rate:%d fmt:%s ch:%d to rate:%d fmt:%s ch:%d\n",
ist->file_index, ist->st->index,
ost->resample_sample_rate, av_get_sample_fmt_name(ost->resample_sample_fmt), ost->resample_channels,
dec->sample_rate, av_get_sample_fmt_name(dec->sample_fmt), dec->channels);
ost->resample_sample_fmt = dec->sample_fmt;
ost->resample_channels = dec->channels;
ost->resample_sample_rate = dec->sample_rate;
if (ost->resample)
audio_resample_close(ost->resample);
}
/* if audio_sync_method is >1 the resampler is needed for audio drift compensation */
if (audio_sync_method <= 1 &&
ost->resample_sample_fmt == enc->sample_fmt &&
ost->resample_channels == enc->channels &&
ost->resample_sample_rate == enc->sample_rate) {
ost->resample = NULL;
ost->audio_resample = 0;
} else if (ost->audio_resample) {
if (dec->sample_fmt != AV_SAMPLE_FMT_S16)
av_log(NULL, AV_LOG_WARNING, "Using s16 intermediate sample format for resampling\n");
ost->resample = av_audio_resample_init(enc->channels, dec->channels,
enc->sample_rate, dec->sample_rate,
enc->sample_fmt, dec->sample_fmt,
16, 10, 0, 0.8);
if (!ost->resample) {
av_log(NULL, AV_LOG_FATAL, "Can not resample %d channels @ %d Hz to %d channels @ %d Hz\n",
dec->channels, dec->sample_rate,
enc->channels, enc->sample_rate);
exit_program(1);
}
}
}
#define MAKE_SFMT_PAIR(a,b) ((a)+AV_SAMPLE_FMT_NB*(b))
if (!ost->audio_resample && dec->sample_fmt != enc->sample_fmt &&
MAKE_SFMT_PAIR(enc->sample_fmt,dec->sample_fmt) != ost->reformat_pair) {
if (ost->reformat_ctx)
av_audio_convert_free(ost->reformat_ctx);
ost->reformat_ctx = av_audio_convert_alloc(enc->sample_fmt, 1,
dec->sample_fmt, 1, NULL, 0);
if (!ost->reformat_ctx) {
av_log(NULL, AV_LOG_FATAL, "Cannot convert %s sample format to %s sample format\n",
av_get_sample_fmt_name(dec->sample_fmt),
av_get_sample_fmt_name(enc->sample_fmt));
exit_program(1);
}
ost->reformat_pair = MAKE_SFMT_PAIR(enc->sample_fmt,dec->sample_fmt);
if (audio_sync_method) {
double delta = get_sync_ipts(ost) * enc->sample_rate - ost->sync_opts -
av_fifo_size(ost->fifo) / (enc->channels * osize);
int idelta = delta * dec->sample_rate / enc->sample_rate;
int byte_delta = idelta * isize * dec->channels;
// FIXME resample delay
if (fabs(delta) > 50) {
if (ist->is_start || fabs(delta) > audio_drift_threshold*enc->sample_rate) {
if (byte_delta < 0) {
byte_delta = FFMAX(byte_delta, -size);
size += byte_delta;
buf -= byte_delta;
av_log(NULL, AV_LOG_VERBOSE, "discarding %d audio samples\n",
-byte_delta / (isize * dec->channels));
ist->is_start = 0;
} else {
static uint8_t *input_tmp = NULL;
input_tmp = av_realloc(input_tmp, byte_delta + size);
if (byte_delta > allocated_for_size - size) {
allocated_for_size = byte_delta + (int64_t)size;
goto need_realloc;
}
generate_silence(input_tmp, dec->sample_fmt, byte_delta);
memcpy(input_tmp + byte_delta, buf, size);
av_log(NULL, AV_LOG_VERBOSE, "adding %d audio samples of silence\n", idelta);
} else if (audio_sync_method > 1) {
int comp = av_clip(delta, -audio_sync_method, audio_sync_method);
av_assert0(ost->audio_resample);
av_log(NULL, AV_LOG_VERBOSE, "compensating audio timestamp drift:%f compensation:%d in:%d\n",
delta, comp, enc->sample_rate);
// fprintf(stderr, "drift:%f len:%d opts:%"PRId64" ipts:%"PRId64" fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(get_sync_ipts(ost) * enc->sample_rate), av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2));
av_resample_compensate(*(struct AVResampleContext**)ost->resample, comp, enc->sample_rate);
}
}
} else
ost->sync_opts = lrintf(get_sync_ipts(ost) * enc->sample_rate) -
av_fifo_size(ost->fifo) / (enc->channels * osize); // FIXME wrong
if (ost->audio_resample) {
buftmp = audio_buf;
size_out = audio_resample(ost->resample,
(short *)buftmp, (short *)buf,
size / (dec->channels * isize));
size_out = size_out * enc->channels * osize;
} else {
buftmp = buf;
size_out = size;
}
if (!ost->audio_resample && dec->sample_fmt != enc->sample_fmt) {
const void *ibuf[6] = { buftmp };
void *obuf[6] = { audio_buf };
int istride[6] = { isize };
int ostride[6] = { osize };
int len = size_out / istride[0];
if (av_audio_convert(ost->reformat_ctx, obuf, ostride, ibuf, istride, len) < 0) {
printf("av_audio_convert() failed\n");
if (exit_on_error)
exit_program(1);
return;
}
buftmp = audio_buf;
}
/* now encode as many frames as possible */
if (!(enc->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) {
/* output resampled raw samples */
if (av_fifo_realloc2(ost->fifo, av_fifo_size(ost->fifo) + size_out) < 0) {
av_log(NULL, AV_LOG_FATAL, "av_fifo_realloc2() failed\n");
exit_program(1);
}
av_fifo_generic_write(ost->fifo, buftmp, size_out, NULL);
frame_bytes = enc->frame_size * osize * enc->channels;
while (av_fifo_size(ost->fifo) >= frame_bytes) {
av_fifo_generic_read(ost->fifo, audio_buf, frame_bytes, NULL);
encode_audio_frame(s, ost, audio_buf, frame_bytes);
encode_audio_frame(s, ost, buftmp, size_out);
}
}
static void pre_process_video_frame(InputStream *ist, AVPicture *picture, void **bufp)
{
AVCodecContext *dec;
AVPicture *picture2;
AVPicture picture_tmp;
uint8_t *buf = 0;
dec = ist->st->codec;
/* deinterlace : must be done before any resize */
if (do_deinterlace) {
int size;
/* create temporary picture */
size = avpicture_get_size(dec->pix_fmt, dec->width, dec->height);
if (!buf)
return;
picture2 = &picture_tmp;
avpicture_fill(picture2, buf, dec->pix_fmt, dec->width, dec->height);
dec->pix_fmt, dec->width, dec->height) < 0) {
/* if error, do not deinterlace */
av_log(NULL, AV_LOG_WARNING, "Deinterlacing failed\n");
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
av_free(buf);
buf = NULL;
picture2 = picture;
}
} else {
picture2 = picture;
}
if (picture != picture2)
*picture = *picture2;
*bufp = buf;
}
static void do_subtitle_out(AVFormatContext *s,
OutputStream *ost,
InputStream *ist,
AVSubtitle *sub,
int64_t pts)
{
static uint8_t *subtitle_out = NULL;
int subtitle_out_max_size = 1024 * 1024;
int subtitle_out_size, nb, i;
AVCodecContext *enc;
AVPacket pkt;
if (pts == AV_NOPTS_VALUE) {
av_log(NULL, AV_LOG_ERROR, "Subtitle packets must have a pts\n");
if (exit_on_error)
exit_program(1);
return;
}
enc = ost->st->codec;
if (!subtitle_out) {
subtitle_out = av_malloc(subtitle_out_max_size);
}
/* Note: DVB subtitle need one packet to draw them and one other
packet to clear them */
/* XXX: signal it in the codec context ? */
if (enc->codec_id == CODEC_ID_DVB_SUBTITLE)
nb = 2;
else
nb = 1;
sub->pts = av_rescale_q(pts, ist->st->time_base, AV_TIME_BASE_Q);
// start_display_time is required to be 0
sub->pts += av_rescale_q(sub->start_display_time, (AVRational){ 1, 1000 }, AV_TIME_BASE_Q);
sub->end_display_time -= sub->start_display_time;
sub->start_display_time = 0;
subtitle_out_size = avcodec_encode_subtitle(enc, subtitle_out,
subtitle_out_max_size, sub);
if (subtitle_out_size < 0) {
av_log(NULL, AV_LOG_FATAL, "Subtitle encoding failed\n");
exit_program(1);
}
av_init_packet(&pkt);
pkt.data = subtitle_out;
pkt.size = subtitle_out_size;
pkt.pts = av_rescale_q(sub->pts, AV_TIME_BASE_Q, ost->st->time_base);
if (enc->codec_id == CODEC_ID_DVB_SUBTITLE) {
/* XXX: the pts correction is handled here. Maybe handling
it in the codec would be better */
if (i == 0)
pkt.pts += 90 * sub->start_display_time;
else
pkt.pts += 90 * sub->end_display_time;
}
write_frame(s, &pkt, ost);
static int bit_buffer_size = 1024 * 256;
static uint8_t *bit_buffer = NULL;
#if !CONFIG_AVFILTER
static void do_video_resample(OutputStream *ost,
InputStream *ist,
AVFrame *in_picture,
AVFrame **out_picture)
int resample_changed = 0;
*out_picture = in_picture;
Anton Khirnov
committed
resample_changed = ost->resample_width != in_picture->width ||
ost->resample_height != in_picture->height ||
ost->resample_pix_fmt != in_picture->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,
ost->resample_width, ost->resample_height, av_get_pix_fmt_name(ost->resample_pix_fmt),
Anton Khirnov
committed
in_picture->width, in_picture->height, av_get_pix_fmt_name(in_picture->format));
ost->video_resample = 1;
}
if (ost->video_resample) {
if (resample_changed) {
/* initialize a new scaler context */
sws_freeContext(ost->img_resample_ctx);
ost->img_resample_ctx = sws_getContext(
ist->st->codec->width,
ist->st->codec->height,
ist->st->codec->pix_fmt,
ost->st->codec->width,
ost->st->codec->height,
ost->st->codec->pix_fmt,
ost->sws_flags, NULL, NULL, NULL);
if (ost->img_resample_ctx == NULL) {
av_log(NULL, AV_LOG_FATAL, "Cannot get resampling context\n");
exit_program(1);
}
}
sws_scale(ost->img_resample_ctx, in_picture->data, in_picture->linesize,
0, ost->resample_height, (*out_picture)->data, (*out_picture)->linesize);
if (resample_changed) {
Anton Khirnov
committed
ost->resample_width = in_picture->width;
ost->resample_height = in_picture->height;
ost->resample_pix_fmt = in_picture->format;
}
static void do_video_out(AVFormatContext *s,
OutputStream *ost,
InputStream *ist,
AVFrame *in_picture,
int *frame_size, float quality)
{
int nb_frames, i, ret, format_video_sync;
double sync_ipts;
enc = ost->st->codec;
sync_ipts = get_sync_ipts(ost) / av_q2d(enc->time_base);
/* by default, we output a single frame */
nb_frames = 1;
*frame_size = 0;
format_video_sync = video_sync_method;
if (format_video_sync == VSYNC_AUTO)
format_video_sync = (s->oformat->flags & AVFMT_NOTIMESTAMPS) ? VSYNC_PASSTHROUGH :
(s->oformat->flags & AVFMT_VARIABLE_FPS) ? VSYNC_VFR : VSYNC_CFR;
if (format_video_sync != VSYNC_PASSTHROUGH) {
double vdelta = sync_ipts - ost->sync_opts;
// FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c
if (vdelta < -1.1)
nb_frames = 0;
else if (format_video_sync == VSYNC_VFR) {
if (vdelta <= -0.6) {
nb_frames = 0;
} else if (vdelta > 0.6)
ost->sync_opts = lrintf(sync_ipts);
} else if (vdelta > 1.1)
nb_frames = lrintf(vdelta);
//fprintf(stderr, "vdelta:%f, ost->sync_opts:%"PRId64", ost->sync_ipts:%f nb_frames:%d\n", vdelta, ost->sync_opts, get_sync_ipts(ost), nb_frames);
av_log(NULL, AV_LOG_VERBOSE, "*** drop!\n");
av_log(NULL, AV_LOG_VERBOSE, "*** %d dup!\n", nb_frames - 1);
nb_frames = FFMIN(nb_frames, ost->max_frames - ost->frame_number);
if (nb_frames <= 0)
return;
#if !CONFIG_AVFILTER
do_video_resample(ost, ist, in_picture, &final_picture);
#else
final_picture = in_picture;
#endif
/* duplicates frame if needed */
AVPacket pkt;
av_init_packet(&pkt);
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
enc->coded_frame->interlaced_frame = in_picture->interlaced_frame;
enc->coded_frame->top_field_first = in_picture->top_field_first;
pkt.data = (uint8_t *)final_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 {
AVFrame big_picture;
/* 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
not be a global option */
big_picture.quality = quality;
big_picture.pict_type = 0;
// big_picture.pts = AV_NOPTS_VALUE;
// big_picture.pts= av_rescale(ost->sync_opts, AV_TIME_BASE*(int64_t)enc->time_base.num, enc->time_base.den);
// av_log(NULL, AV_LOG_DEBUG, "%"PRId64" -> encoder\n", 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_video(enc,
bit_buffer, bit_buffer_size,
&big_picture);
if (ret < 0) {
av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n");
exit_program(1);
}
if (ret > 0) {
pkt.data = bit_buffer;
pkt.size = ret;
if (enc->coded_frame->pts != AV_NOPTS_VALUE)
pkt.pts = av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
/*av_log(NULL, AV_LOG_DEBUG, "encoder -> %"PRId64"/%"PRId64"\n",
pkt.pts != AV_NOPTS_VALUE ? av_rescale(pkt.pts, enc->time_base.den, AV_TIME_BASE*(int64_t)enc->time_base.num) : -1,
pkt.dts != AV_NOPTS_VALUE ? av_rescale(pkt.dts, enc->time_base.den, AV_TIME_BASE*(int64_t)enc->time_base.num) : -1);*/
pkt.flags |= AV_PKT_FLAG_KEY;
write_frame(s, &pkt, ost);
*frame_size = ret;
video_size += ret;
// fprintf(stderr,"\nFrame: %3d size: %5d type: %d",
// enc->frame_number-1, ret, enc->pict_type);
/* if two pass, output log */
if (ost->logfile && enc->stats_out) {
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++;
static double psnr(double d)
{
return -10.0 * log(d) / log(10.0);
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
}
static void do_video_stats(AVFormatContext *os, OutputStream *ost,
int frame_size)
{
AVCodecContext *enc;
int frame_number;
double ti1, bitrate, avg_bitrate;
/* this is executed just the first time do_video_stats is called */
if (!vstats_file) {
vstats_file = fopen(vstats_filename, "w");
if (!vstats_file) {
perror("fopen");
exit_program(1);
}
}
enc = ost->st->codec;
if (enc->codec_type == AVMEDIA_TYPE_VIDEO) {
frame_number = ost->frame_number;
fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number, enc->coded_frame->quality / (float)FF_QP2LAMBDA);
if (enc->flags&CODEC_FLAG_PSNR)
fprintf(vstats_file, "PSNR= %6.2f ", psnr(enc->coded_frame->error[0] / (enc->width * enc->height * 255.0 * 255.0)));
fprintf(vstats_file,"f_size= %6d ", frame_size);
/* compute pts value */
ti1 = ost->sync_opts * av_q2d(enc->time_base);
if (ti1 < 0.01)
ti1 = 0.01;
bitrate = (frame_size * 8) / av_q2d(enc->time_base) / 1000.0;
avg_bitrate = (double)(video_size * 8) / ti1 / 1000.0;
fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ",
(double)video_size / 1024, ti1, bitrate, avg_bitrate);
fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(enc->coded_frame->pict_type));
}
}
Anton Khirnov
committed
static void print_report(OutputFile *output_files,
OutputStream *ost_table, int nb_ostreams,
int is_last_report, int64_t timer_start)
{
char buf[1024];
OutputStream *ost;
AVFormatContext *oc;
int64_t total_size;
AVCodecContext *enc;
int frame_number, vid, i;
double bitrate, ti1, pts;
static int64_t last_time = -1;
static int qp_histogram[52];
if (!print_stats && !is_last_report)
return;
if (!is_last_report) {
int64_t cur_time;
/* display the report every 0.5 seconds */
cur_time = av_gettime();
if (last_time == -1) {
last_time = cur_time;
return;
}
if ((cur_time - last_time) < 500000)
return;
last_time = cur_time;
}
Anton Khirnov
committed
oc = output_files[0].ctx;
total_size = avio_size(oc->pb);
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';
ti1 = 1e10;
vid = 0;
ost = &ost_table[i];
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 t = (av_gettime() - timer_start) / 1000000.0;
frame_number = ost->frame_number;
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "frame=%5d fps=%3d q=%3.1f ",
frame_number, (t > 1) ? (int)(frame_number / t + 0.5) : 0, q);
if (is_last_report)
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "L");
int j;
int qp = lrintf(q);
for (j = 0; j < 32; j++)
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%X", (int)lrintf(log(qp_histogram[j] + 1) / log(2)));
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;
error_sum += error;
scale_sum += scale;
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%c:%2.2f ", type[j], psnr(error / scale));
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "*:%2.2f ", psnr(error_sum / scale_sum));
}
vid = 1;
}
/* compute min output value */
pts = (double)ost->st->pts.val * av_q2d(ost->st->time_base);
if ((pts < ti1) && (pts > 0))
ti1 = pts;
}
if (ti1 < 0.01)
ti1 = 0.01;
bitrate = (double)(total_size * 8) / ti1 / 1000.0;
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
"size=%8.0fkB time=%0.2f bitrate=%6.1fkbits/s",
(double)total_size / 1024, ti1, 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);
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
);
}
}
static void flush_encoders(OutputStream *ost_table, int nb_ostreams)
{
int i, ret;
for (i = 0; i < nb_ostreams; i++) {
OutputStream *ost = &ost_table[i];
AVCodecContext *enc = ost->st->codec;
AVFormatContext *os = output_files[ost->file_index].ctx;
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;
int fifo_bytes;
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);
/* pad last frame with silence if needed */
if (!(enc->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME)) {
frame_bytes = enc->frame_size * enc->channels *
av_get_bytes_per_sample(enc->sample_fmt);
if (allocated_audio_buf_size < frame_bytes)
exit_program(1);
generate_silence(audio_buf+fifo_bytes, enc->sample_fmt, frame_bytes - fifo_bytes);
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;
}
}
break;
case AVMEDIA_TYPE_VIDEO:
ret = avcodec_encode_video(enc, bit_buffer, bit_buffer_size, NULL);
if (ret < 0) {
av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n");
exit_program(1);
}
video_size += ret;
if (enc->coded_frame && enc->coded_frame->key_frame)
pkt.flags |= AV_PKT_FLAG_KEY;
if (ost->logfile && enc->stats_out) {
fprintf(ost->logfile, "%s", enc->stats_out);
}
if (ret <= 0) {
stop_encoding = 1;
break;
}
pkt.data = bit_buffer;
pkt.size = ret;
if (enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
pkt.pts = av_rescale_q(enc->coded_frame->pts, 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 = ist - input_streams;
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,
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
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];
int64_t ost_tb_start_time = av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base);
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->pts, 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
) {
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;
}
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->pts, 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);
if (ret < 0) {
}
if (!*got_output) {
/* no audio frame */
return ret;
/* 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->next_pts = decoded_frame->pts;
/* increment next_pts 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;
// 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) {
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
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);
}
break;
}
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);
}
break;
}
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;
}
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);
return ret;
static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_t *pkt_pts)
{
AVFrame *decoded_frame, *filtered_frame = NULL;
void *buffer_to_free = NULL;
int i, ret = 0;
float quality;
#if CONFIG_AVFILTER
int frame_available = 1;
#endif
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;
pkt->pts = *pkt_pts;
pkt->dts = ist->pts;
*pkt_pts = AV_NOPTS_VALUE;
ret = avcodec_decode_video2(ist->st->codec,
decoded_frame, got_output, pkt);
if (ret < 0)
quality = same_quant ? decoded_frame->quality : 0;
if (!*got_output) {
/* no picture yet */
return ret;
}
ist->next_pts = ist->pts = guess_correct_pts(&ist->pts_ctx, decoded_frame->pkt_pts,
decoded_frame->pkt_dts);
if (pkt->duration)
ist->next_pts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q);
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_pts += ((int64_t)AV_TIME_BASE *
ist->st->codec->time_base.num * ticks) /
ist->st->codec->time_base.den;
}
pkt->size = 0;
pre_process_video_frame(ist, (AVPicture *)decoded_frame, &buffer_to_free);
rate_emu_sleep(ist);
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = &output_streams[i];
int frame_size, resample_changed;
if (!check_output_constraints(ist, ost) || !ost->encoding_needed)
continue;
#if CONFIG_AVFILTER
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
resample_changed = ost->resample_width != decoded_frame->width ||
ost->resample_height != decoded_frame->height ||
ost->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,
ost->resample_width, ost->resample_height, av_get_pix_fmt_name(ost->resample_pix_fmt),
decoded_frame->width, decoded_frame->height, av_get_pix_fmt_name(decoded_frame->format));
avfilter_graph_free(&ost->graph);
if (configure_video_filters(ist, ost)) {
av_log(NULL, AV_LOG_FATAL, "Error reinitializing filters!\n");
exit_program(1);
}
ost->resample_width = decoded_frame->width;
ost->resample_height = decoded_frame->height;
ost->resample_pix_fmt = decoded_frame->format;
}
if (ist->st->sample_aspect_ratio.num)
decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio;
if (ist->st->codec->codec->capabilities & CODEC_CAP_DR1) {
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->pts = ist->pts;
fb->buf->priv = buf;
fb->buf->free = filter_release_buffer;
buf->refcount++;
av_buffersrc_buffer(ost->input_video_filter, fb);
} else