mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2024-12-26 01:02:33 +00:00
fftools/ffmpeg_enc: add an AVClass to Encoder
Log decoder messages to the encoder rather than OutputStream. This is a step towards decoupling encoders from muxers, similarly to what was previously done to decoders and demuxers.
This commit is contained in:
parent
78170120ca
commit
70f7bbeade
@ -858,7 +858,7 @@ int dec_request_view(Decoder *dec, const ViewSpecifier *vs,
|
|||||||
SchedulerNode *src);
|
SchedulerNode *src);
|
||||||
|
|
||||||
int enc_alloc(Encoder **penc, const AVCodec *codec,
|
int enc_alloc(Encoder **penc, const AVCodec *codec,
|
||||||
Scheduler *sch, unsigned sch_idx);
|
Scheduler *sch, unsigned sch_idx, void *log_parent);
|
||||||
void enc_free(Encoder **penc);
|
void enc_free(Encoder **penc);
|
||||||
|
|
||||||
int enc_open(void *opaque, const AVFrame *frame);
|
int enc_open(void *opaque, const AVFrame *frame);
|
||||||
|
@ -39,6 +39,10 @@
|
|||||||
#include "libavcodec/avcodec.h"
|
#include "libavcodec/avcodec.h"
|
||||||
|
|
||||||
struct Encoder {
|
struct Encoder {
|
||||||
|
const AVClass *class;
|
||||||
|
void *log_parent;
|
||||||
|
char log_name[32];
|
||||||
|
|
||||||
// combined size of all the packets received from the encoder
|
// combined size of all the packets received from the encoder
|
||||||
uint64_t data_size;
|
uint64_t data_size;
|
||||||
|
|
||||||
@ -68,8 +72,22 @@ void enc_free(Encoder **penc)
|
|||||||
av_freep(penc);
|
av_freep(penc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *enc_item_name(void *obj)
|
||||||
|
{
|
||||||
|
const Encoder *e = obj;
|
||||||
|
|
||||||
|
return e->log_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const AVClass enc_class = {
|
||||||
|
.class_name = "Encoder",
|
||||||
|
.version = LIBAVUTIL_VERSION_INT,
|
||||||
|
.parent_log_context_offset = offsetof(Encoder, log_parent),
|
||||||
|
.item_name = enc_item_name,
|
||||||
|
};
|
||||||
|
|
||||||
int enc_alloc(Encoder **penc, const AVCodec *codec,
|
int enc_alloc(Encoder **penc, const AVCodec *codec,
|
||||||
Scheduler *sch, unsigned sch_idx)
|
Scheduler *sch, unsigned sch_idx, void *log_parent)
|
||||||
{
|
{
|
||||||
Encoder *enc;
|
Encoder *enc;
|
||||||
|
|
||||||
@ -79,9 +97,14 @@ int enc_alloc(Encoder **penc, const AVCodec *codec,
|
|||||||
if (!enc)
|
if (!enc)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
|
enc->class = &enc_class;
|
||||||
|
enc->log_parent = log_parent;
|
||||||
|
|
||||||
enc->sch = sch;
|
enc->sch = sch;
|
||||||
enc->sch_idx = sch_idx;
|
enc->sch_idx = sch_idx;
|
||||||
|
|
||||||
|
snprintf(enc->log_name, sizeof(enc->log_name), "enc:%s", codec->name);
|
||||||
|
|
||||||
*penc = enc;
|
*penc = enc;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -314,14 +337,14 @@ int enc_open(void *opaque, const AVFrame *frame)
|
|||||||
|
|
||||||
ret = hw_device_setup_for_encode(ost, frame ? frame->hw_frames_ctx : NULL);
|
ret = hw_device_setup_for_encode(ost, frame ? frame->hw_frames_ctx : NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
av_log(ost, AV_LOG_ERROR,
|
av_log(e, AV_LOG_ERROR,
|
||||||
"Encoding hardware device setup failed: %s\n", av_err2str(ret));
|
"Encoding hardware device setup failed: %s\n", av_err2str(ret));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = avcodec_open2(ost->enc_ctx, enc, NULL)) < 0) {
|
if ((ret = avcodec_open2(ost->enc_ctx, enc, NULL)) < 0) {
|
||||||
if (ret != AVERROR_EXPERIMENTAL)
|
if (ret != AVERROR_EXPERIMENTAL)
|
||||||
av_log(ost, AV_LOG_ERROR, "Error while opening encoder - maybe "
|
av_log(e, AV_LOG_ERROR, "Error while opening encoder - maybe "
|
||||||
"incorrect parameters such as bit_rate, rate, width or height.\n");
|
"incorrect parameters such as bit_rate, rate, width or height.\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -333,12 +356,12 @@ int enc_open(void *opaque, const AVFrame *frame)
|
|||||||
|
|
||||||
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 */)
|
ost->enc_ctx->codec_id != AV_CODEC_ID_CODEC2 /* don't complain about 700 bit/s modes */)
|
||||||
av_log(ost, AV_LOG_WARNING, "The bitrate parameter is set too low."
|
av_log(e, AV_LOG_WARNING, "The bitrate parameter is set too low."
|
||||||
" It takes bits/s as argument, not kbits/s\n");
|
" It takes bits/s as argument, not kbits/s\n");
|
||||||
|
|
||||||
ret = avcodec_parameters_from_context(ost->par_in, ost->enc_ctx);
|
ret = avcodec_parameters_from_context(ost->par_in, ost->enc_ctx);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
av_log(ost, AV_LOG_FATAL,
|
av_log(e, AV_LOG_FATAL,
|
||||||
"Error initializing the output stream codec context.\n");
|
"Error initializing the output stream codec context.\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -375,7 +398,7 @@ static int do_subtitle_out(OutputFile *of, OutputStream *ost, const AVSubtitle *
|
|||||||
int64_t pts;
|
int64_t pts;
|
||||||
|
|
||||||
if (sub->pts == AV_NOPTS_VALUE) {
|
if (sub->pts == AV_NOPTS_VALUE) {
|
||||||
av_log(ost, AV_LOG_ERROR, "Subtitle packets must have a pts\n");
|
av_log(e, AV_LOG_ERROR, "Subtitle packets must have a pts\n");
|
||||||
return exit_on_error ? AVERROR(EINVAL) : 0;
|
return exit_on_error ? AVERROR(EINVAL) : 0;
|
||||||
}
|
}
|
||||||
if ((of->start_time != AV_NOPTS_VALUE && sub->pts < of->start_time))
|
if ((of->start_time != AV_NOPTS_VALUE && sub->pts < of->start_time))
|
||||||
@ -424,7 +447,7 @@ static int do_subtitle_out(OutputFile *of, OutputStream *ost, const AVSubtitle *
|
|||||||
|
|
||||||
subtitle_out_size = avcodec_encode_subtitle(enc, pkt->data, pkt->size, &local_sub);
|
subtitle_out_size = avcodec_encode_subtitle(enc, pkt->data, pkt->size, &local_sub);
|
||||||
if (subtitle_out_size < 0) {
|
if (subtitle_out_size < 0) {
|
||||||
av_log(ost, AV_LOG_FATAL, "Subtitle encoding failed\n");
|
av_log(e, AV_LOG_FATAL, "Subtitle encoding failed\n");
|
||||||
return subtitle_out_size;
|
return subtitle_out_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -619,7 +642,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
|
|||||||
ost->samples_encoded += frame->nb_samples;
|
ost->samples_encoded += frame->nb_samples;
|
||||||
|
|
||||||
if (debug_ts) {
|
if (debug_ts) {
|
||||||
av_log(ost, AV_LOG_INFO, "encoder <- type:%s "
|
av_log(e, AV_LOG_INFO, "encoder <- type:%s "
|
||||||
"frame_pts:%s frame_pts_time:%s time_base:%d/%d\n",
|
"frame_pts:%s frame_pts_time:%s time_base:%d/%d\n",
|
||||||
type_desc,
|
type_desc,
|
||||||
av_ts2str(frame->pts), av_ts2timestr(frame->pts, &enc->time_base),
|
av_ts2str(frame->pts), av_ts2timestr(frame->pts, &enc->time_base),
|
||||||
@ -634,7 +657,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
|
|||||||
|
|
||||||
ret = avcodec_send_frame(enc, frame);
|
ret = avcodec_send_frame(enc, frame);
|
||||||
if (ret < 0 && !(ret == AVERROR_EOF && !frame)) {
|
if (ret < 0 && !(ret == AVERROR_EOF && !frame)) {
|
||||||
av_log(ost, AV_LOG_ERROR, "Error submitting %s frame to the encoder\n",
|
av_log(e, AV_LOG_ERROR, "Error submitting %s frame to the encoder\n",
|
||||||
type_desc);
|
type_desc);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -659,7 +682,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
|
|||||||
return 0;
|
return 0;
|
||||||
} else if (ret < 0) {
|
} else if (ret < 0) {
|
||||||
if (ret != AVERROR_EOF)
|
if (ret != AVERROR_EOF)
|
||||||
av_log(ost, AV_LOG_ERROR, "%s encoding failed\n", type_desc);
|
av_log(e, AV_LOG_ERROR, "%s encoding failed\n", type_desc);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -693,7 +716,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
|
|||||||
e->packets_encoded);
|
e->packets_encoded);
|
||||||
|
|
||||||
if (debug_ts) {
|
if (debug_ts) {
|
||||||
av_log(ost, AV_LOG_INFO, "encoder -> type:%s "
|
av_log(e, AV_LOG_INFO, "encoder -> type:%s "
|
||||||
"pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s "
|
"pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s "
|
||||||
"duration:%s duration_time:%s\n",
|
"duration:%s duration_time:%s\n",
|
||||||
type_desc,
|
type_desc,
|
||||||
@ -764,6 +787,7 @@ force_keyframe:
|
|||||||
|
|
||||||
static int frame_encode(OutputStream *ost, AVFrame *frame, AVPacket *pkt)
|
static int frame_encode(OutputStream *ost, AVFrame *frame, AVPacket *pkt)
|
||||||
{
|
{
|
||||||
|
Encoder *e = ost->enc;
|
||||||
OutputFile *of = ost->file;
|
OutputFile *of = ost->file;
|
||||||
enum AVMediaType type = ost->type;
|
enum AVMediaType type = ost->type;
|
||||||
|
|
||||||
@ -782,7 +806,7 @@ static int frame_encode(OutputStream *ost, AVFrame *frame, AVPacket *pkt)
|
|||||||
|
|
||||||
if (type == AVMEDIA_TYPE_VIDEO) {
|
if (type == AVMEDIA_TYPE_VIDEO) {
|
||||||
frame->quality = ost->enc_ctx->global_quality;
|
frame->quality = ost->enc_ctx->global_quality;
|
||||||
frame->pict_type = forced_kf_apply(ost, &ost->kf, frame);
|
frame->pict_type = forced_kf_apply(e, &ost->kf, frame);
|
||||||
|
|
||||||
#if FFMPEG_OPT_TOP
|
#if FFMPEG_OPT_TOP
|
||||||
if (ost->top_field_first >= 0) {
|
if (ost->top_field_first >= 0) {
|
||||||
@ -793,7 +817,7 @@ static int frame_encode(OutputStream *ost, AVFrame *frame, AVPacket *pkt)
|
|||||||
} else {
|
} else {
|
||||||
if (!(ost->enc_ctx->codec->capabilities & AV_CODEC_CAP_PARAM_CHANGE) &&
|
if (!(ost->enc_ctx->codec->capabilities & AV_CODEC_CAP_PARAM_CHANGE) &&
|
||||||
ost->enc_ctx->ch_layout.nb_channels != frame->ch_layout.nb_channels) {
|
ost->enc_ctx->ch_layout.nb_channels != frame->ch_layout.nb_channels) {
|
||||||
av_log(ost, AV_LOG_ERROR,
|
av_log(e, AV_LOG_ERROR,
|
||||||
"Audio channel count changed and encoder does not support parameter changes\n");
|
"Audio channel count changed and encoder does not support parameter changes\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -867,14 +891,14 @@ int encoder_thread(void *arg)
|
|||||||
input_status = sch_enc_receive(e->sch, e->sch_idx, et.frame);
|
input_status = sch_enc_receive(e->sch, e->sch_idx, et.frame);
|
||||||
if (input_status < 0) {
|
if (input_status < 0) {
|
||||||
if (input_status == AVERROR_EOF) {
|
if (input_status == AVERROR_EOF) {
|
||||||
av_log(ost, AV_LOG_VERBOSE, "Encoder thread received EOF\n");
|
av_log(e, AV_LOG_VERBOSE, "Encoder thread received EOF\n");
|
||||||
if (e->opened)
|
if (e->opened)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
av_log(ost, AV_LOG_ERROR, "Could not open encoder before EOF\n");
|
av_log(e, AV_LOG_ERROR, "Could not open encoder before EOF\n");
|
||||||
ret = AVERROR(EINVAL);
|
ret = AVERROR(EINVAL);
|
||||||
} else {
|
} else {
|
||||||
av_log(ost, AV_LOG_ERROR, "Error receiving a frame for encoding: %s\n",
|
av_log(e, AV_LOG_ERROR, "Error receiving a frame for encoding: %s\n",
|
||||||
av_err2str(ret));
|
av_err2str(ret));
|
||||||
ret = input_status;
|
ret = input_status;
|
||||||
}
|
}
|
||||||
@ -893,9 +917,9 @@ int encoder_thread(void *arg)
|
|||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (ret == AVERROR_EOF)
|
if (ret == AVERROR_EOF)
|
||||||
av_log(ost, AV_LOG_VERBOSE, "Encoder returned EOF, finishing\n");
|
av_log(e, AV_LOG_VERBOSE, "Encoder returned EOF, finishing\n");
|
||||||
else
|
else
|
||||||
av_log(ost, AV_LOG_ERROR, "Error encoding a frame: %s\n",
|
av_log(e, AV_LOG_ERROR, "Error encoding a frame: %s\n",
|
||||||
av_err2str(ret));
|
av_err2str(ret));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -905,7 +929,7 @@ int encoder_thread(void *arg)
|
|||||||
if (ret == 0 || ret == AVERROR_EOF) {
|
if (ret == 0 || ret == AVERROR_EOF) {
|
||||||
ret = frame_encode(ost, NULL, et.pkt);
|
ret = frame_encode(ost, NULL, et.pkt);
|
||||||
if (ret < 0 && ret != AVERROR_EOF)
|
if (ret < 0 && ret != AVERROR_EOF)
|
||||||
av_log(ost, AV_LOG_ERROR, "Error flushing encoder: %s\n",
|
av_log(e, AV_LOG_ERROR, "Error flushing encoder: %s\n",
|
||||||
av_err2str(ret));
|
av_err2str(ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1227,7 +1227,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
|
|||||||
return ret;
|
return ret;
|
||||||
ms->sch_idx_enc = ret;
|
ms->sch_idx_enc = ret;
|
||||||
|
|
||||||
ret = enc_alloc(&ost->enc, enc, mux->sch, ms->sch_idx_enc);
|
ret = enc_alloc(&ost->enc, enc, mux->sch, ms->sch_idx_enc, ost);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user