|
|
|
@ -831,63 +831,96 @@ static int init_output_stream_wrapper(OutputStream *ost, AVFrame *frame, |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void do_audio_out(OutputFile *of, OutputStream *ost, |
|
|
|
|
AVFrame *frame) |
|
|
|
|
static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) |
|
|
|
|
{ |
|
|
|
|
AVCodecContext *enc = ost->enc_ctx; |
|
|
|
|
AVPacket *pkt = ost->pkt; |
|
|
|
|
AVCodecContext *enc = ost->enc_ctx; |
|
|
|
|
AVPacket *pkt = ost->pkt; |
|
|
|
|
const char *type_desc = av_get_media_type_string(enc->codec_type); |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
adjust_frame_pts_to_encoder_tb(of, ost, frame); |
|
|
|
|
|
|
|
|
|
if (!check_recording_time(ost)) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
if (frame->pts == AV_NOPTS_VALUE || audio_sync_method < 0) |
|
|
|
|
frame->pts = ost->sync_opts; |
|
|
|
|
ost->sync_opts = frame->pts + frame->nb_samples; |
|
|
|
|
ost->samples_encoded += frame->nb_samples; |
|
|
|
|
ost->frames_encoded++; |
|
|
|
|
|
|
|
|
|
update_benchmark(NULL); |
|
|
|
|
|
|
|
|
|
if (debug_ts) { |
|
|
|
|
av_log(NULL, AV_LOG_INFO, "encoder <- type:audio " |
|
|
|
|
av_log(NULL, AV_LOG_INFO, "encoder <- type:%s " |
|
|
|
|
"frame_pts:%s frame_pts_time:%s time_base:%d/%d\n", |
|
|
|
|
type_desc, |
|
|
|
|
av_ts2str(frame->pts), av_ts2timestr(frame->pts, &enc->time_base), |
|
|
|
|
enc->time_base.num, enc->time_base.den); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ret = avcodec_send_frame(enc, frame); |
|
|
|
|
if (ret < 0) |
|
|
|
|
goto error; |
|
|
|
|
if (ret < 0) { |
|
|
|
|
av_log(NULL, AV_LOG_ERROR, "Error submitting %s frame to the encoder\n", |
|
|
|
|
type_desc); |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
while (1) { |
|
|
|
|
ret = avcodec_receive_packet(enc, pkt); |
|
|
|
|
update_benchmark("encode_%s %d.%d", type_desc, |
|
|
|
|
ost->file_index, ost->index); |
|
|
|
|
if (ret == AVERROR(EAGAIN)) |
|
|
|
|
break; |
|
|
|
|
if (ret < 0) |
|
|
|
|
goto error; |
|
|
|
|
return 0; |
|
|
|
|
else if (ret < 0) { |
|
|
|
|
av_log(NULL, AV_LOG_ERROR, "%s encoding failed\n", type_desc); |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
update_benchmark("encode_audio %d.%d", ost->file_index, ost->index); |
|
|
|
|
if (debug_ts) { |
|
|
|
|
av_log(NULL, AV_LOG_INFO, "encoder -> type:%s " |
|
|
|
|
"pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s " |
|
|
|
|
"duration:%s duration_time:%s\n", |
|
|
|
|
type_desc, |
|
|
|
|
av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base), |
|
|
|
|
av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base), |
|
|
|
|
av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase); |
|
|
|
|
|
|
|
|
|
if (debug_ts) { |
|
|
|
|
av_log(NULL, AV_LOG_INFO, "encoder -> type:audio " |
|
|
|
|
av_log(NULL, AV_LOG_INFO, "encoder -> type:%s " |
|
|
|
|
"pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s " |
|
|
|
|
"duration:%s duration_time:%s\n", |
|
|
|
|
type_desc, |
|
|
|
|
av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base), |
|
|
|
|
av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base), |
|
|
|
|
av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (enc->codec_type == AVMEDIA_TYPE_VIDEO && vstats_filename) |
|
|
|
|
do_video_stats(ost, pkt->size); |
|
|
|
|
|
|
|
|
|
output_packet(of, pkt, ost, 0); |
|
|
|
|
|
|
|
|
|
/* if two pass, output log */ |
|
|
|
|
if (ost->logfile && enc->stats_out) |
|
|
|
|
fprintf(ost->logfile, "%s", enc->stats_out); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return; |
|
|
|
|
error: |
|
|
|
|
av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n"); |
|
|
|
|
exit_program(1); |
|
|
|
|
av_assert0(0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void do_audio_out(OutputFile *of, OutputStream *ost, |
|
|
|
|
AVFrame *frame) |
|
|
|
|
{ |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
adjust_frame_pts_to_encoder_tb(of, ost, frame); |
|
|
|
|
|
|
|
|
|
if (!check_recording_time(ost)) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
if (frame->pts == AV_NOPTS_VALUE || audio_sync_method < 0) |
|
|
|
|
frame->pts = ost->sync_opts; |
|
|
|
|
ost->sync_opts = frame->pts + frame->nb_samples; |
|
|
|
|
ost->samples_encoded += frame->nb_samples; |
|
|
|
|
|
|
|
|
|
ret = encode_frame(of, ost, frame); |
|
|
|
|
if (ret < 0) |
|
|
|
|
exit_program(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void do_subtitle_out(OutputFile *of, |
|
|
|
@ -979,14 +1012,12 @@ static void do_video_out(OutputFile *of, |
|
|
|
|
AVFrame *next_picture) |
|
|
|
|
{ |
|
|
|
|
int ret; |
|
|
|
|
AVPacket *pkt = ost->pkt; |
|
|
|
|
AVCodecContext *enc = ost->enc_ctx; |
|
|
|
|
AVRational frame_rate; |
|
|
|
|
int nb_frames, nb0_frames, i; |
|
|
|
|
double delta, delta0; |
|
|
|
|
double duration = 0; |
|
|
|
|
double sync_ipts = AV_NOPTS_VALUE; |
|
|
|
|
int frame_size = 0; |
|
|
|
|
InputStream *ist = NULL; |
|
|
|
|
AVFilterContext *filter = ost->filter->filter; |
|
|
|
|
|
|
|
|
@ -1179,73 +1210,17 @@ static void do_video_out(OutputFile *of, |
|
|
|
|
av_log(NULL, AV_LOG_DEBUG, "Forced keyframe at time %f\n", pts_time); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
update_benchmark(NULL); |
|
|
|
|
if (debug_ts) { |
|
|
|
|
av_log(NULL, AV_LOG_INFO, "encoder <- type:video " |
|
|
|
|
"frame_pts:%s frame_pts_time:%s time_base:%d/%d\n", |
|
|
|
|
av_ts2str(in_picture->pts), av_ts2timestr(in_picture->pts, &enc->time_base), |
|
|
|
|
enc->time_base.num, enc->time_base.den); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ost->frames_encoded++; |
|
|
|
|
|
|
|
|
|
ret = avcodec_send_frame(enc, in_picture); |
|
|
|
|
ret = encode_frame(of, ost, 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); |
|
|
|
|
update_benchmark("encode_video %d.%d", ost->file_index, ost->index); |
|
|
|
|
if (ret == AVERROR(EAGAIN)) |
|
|
|
|
break; |
|
|
|
|
if (ret < 0) |
|
|
|
|
goto error; |
|
|
|
|
|
|
|
|
|
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 " |
|
|
|
|
"duration:%s duration_time:%s\n", |
|
|
|
|
av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base), |
|
|
|
|
av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base), |
|
|
|
|
av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase); |
|
|
|
|
|
|
|
|
|
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 " |
|
|
|
|
"duration:%s duration_time:%s\n", |
|
|
|
|
av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ost->mux_timebase), |
|
|
|
|
av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ost->mux_timebase), |
|
|
|
|
av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ost->mux_timebase)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
frame_size = pkt->size; |
|
|
|
|
output_packet(of, pkt, ost, 0); |
|
|
|
|
exit_program(1); |
|
|
|
|
|
|
|
|
|
/* if two pass, output log */ |
|
|
|
|
if (ost->logfile && enc->stats_out) { |
|
|
|
|
fprintf(ost->logfile, "%s", enc->stats_out); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
ost->sync_opts++; |
|
|
|
|
ost->frame_number++; |
|
|
|
|
|
|
|
|
|
if (vstats_filename && frame_size) |
|
|
|
|
do_video_stats(ost, frame_size); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
av_frame_unref(ost->last_frame); |
|
|
|
|
if (next_picture) |
|
|
|
|
av_frame_move_ref(ost->last_frame, next_picture); |
|
|
|
|
|
|
|
|
|
return; |
|
|
|
|
error: |
|
|
|
|
av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n"); |
|
|
|
|
exit_program(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static double psnr(double d) |
|
|
|
|