mirror of
https://github.com/livepeer/lpms
synced 2025-09-26 19:51:36 +08:00
ffmpeg: Re-init encoder on resolution change.
This commit is contained in:
@@ -255,7 +255,11 @@ int open_output(struct output_ctx *octx, struct input_ctx *ictx)
|
||||
if(strcmp(octx->xcoderParams,"")!=0){
|
||||
av_opt_set(vc->priv_data, "xcoder-params", octx->xcoderParams, 0);
|
||||
}
|
||||
ret = avcodec_open2(vc, codec, &octx->video->opts);
|
||||
// copy codec options and open encoder
|
||||
AVDictionary *opts = NULL;
|
||||
if (octx->video->opts) av_dict_copy(&opts, octx->video->opts, 0);
|
||||
ret = avcodec_open2(vc, codec, &opts);
|
||||
if (opts) av_dict_free(&opts);
|
||||
if (ret < 0) LPMS_ERR(open_output_err, "Error opening video encoder");
|
||||
octx->hw_type = ictx->hw_type;
|
||||
}
|
||||
@@ -338,6 +342,75 @@ int encode(AVCodecContext* encoder, AVFrame *frame, struct output_ctx* octx, AVS
|
||||
AVPacket *pkt = NULL;
|
||||
|
||||
if (AVMEDIA_TYPE_VIDEO == ost->codecpar->codec_type && frame) {
|
||||
if (encoder->width != frame->width || encoder->height != frame->height) {
|
||||
// Frame dimensions changed so need to re-init encoder
|
||||
const AVCodec *codec = avcodec_find_encoder_by_name(octx->video->name);
|
||||
if (!codec) LPMS_ERR(encode_cleanup, "Unable to find encoder");
|
||||
AVCodecContext *vc = avcodec_alloc_context3(codec);
|
||||
if (!vc) LPMS_ERR(encode_cleanup, "Unable to alloc video encoder");
|
||||
// copy any additional params needed from AVCodecParameters
|
||||
AVCodecParameters *codecpar = avcodec_parameters_alloc();
|
||||
if (!codecpar) LPMS_ERR(encode_cleanup, "Unable to alloc codec params");
|
||||
avcodec_parameters_from_context(codecpar, encoder);
|
||||
avcodec_parameters_to_context(vc, codecpar);
|
||||
avcodec_parameters_free(&codecpar);
|
||||
// manually set some additional fields
|
||||
vc->width = frame->width;
|
||||
vc->height = frame->height;
|
||||
vc->time_base = encoder->time_base;
|
||||
vc->flags = encoder->flags;
|
||||
vc->rc_min_rate = encoder->rc_min_rate;
|
||||
vc->rc_max_rate = encoder->rc_max_rate;
|
||||
vc->bit_rate = encoder->bit_rate;
|
||||
vc->rc_buffer_size = encoder->rc_buffer_size;
|
||||
if (encoder->hw_frames_ctx) {
|
||||
if (octx->vf.active && av_buffersink_get_hw_frames_ctx(octx->vf.sink_ctx)) {
|
||||
vc->hw_frames_ctx =
|
||||
av_buffer_ref(av_buffersink_get_hw_frames_ctx(octx->vf.sink_ctx));
|
||||
if (!vc->hw_frames_ctx) {
|
||||
LPMS_ERR(encode_cleanup, "Unable to re-alloc encoder hwframes")
|
||||
}
|
||||
} else {
|
||||
vc->hw_frames_ctx = av_buffer_ref(encoder->hw_frames_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
// flush old encoder
|
||||
AVPacket *pkt = av_packet_alloc();
|
||||
if (!pkt) LPMS_ERR(encode_cleanup, "Unable to alloc flush packet");
|
||||
avcodec_send_frame(encoder, NULL);
|
||||
AVRational time_base = encoder->time_base;
|
||||
while (!ret) {
|
||||
av_packet_unref(pkt);
|
||||
ret = avcodec_receive_packet(encoder, pkt);
|
||||
// TODO error handling
|
||||
if (!ret) {
|
||||
if (!octx->fps.den && octx->vf.active) {
|
||||
// adjust timestamps for filter passthrough
|
||||
time_base = octx->vf.time_base;
|
||||
int64_t pts_dts = pkt->pts - pkt->dts;
|
||||
pkt->pts = (int64_t)pkt->opaque; // already in filter timebase
|
||||
pkt->dts = pkt->pts - av_rescale_q(pts_dts, encoder->time_base, time_base);
|
||||
}
|
||||
mux(pkt, time_base, octx, ost);
|
||||
} else if (AVERROR_EOF != ret) {
|
||||
av_packet_free(&pkt);
|
||||
LPMS_ERR(encode_cleanup, "did not get eof");
|
||||
}
|
||||
}
|
||||
av_packet_free(&pkt);
|
||||
avcodec_free_context(&octx->vc);
|
||||
|
||||
// copy codec options and open encoder
|
||||
AVDictionary *opts = NULL;
|
||||
if (octx->video->opts) av_dict_copy(&opts, octx->video->opts, 0);
|
||||
ret = avcodec_open2(vc, codec, &opts);
|
||||
if (opts) av_dict_free(&opts);
|
||||
if (ret < 0) LPMS_ERR(encode_cleanup, "Error opening video encoder");
|
||||
if (octx->gop_pts_len) octx->next_kf_pts = frame->pts + octx->gop_pts_len;
|
||||
octx->vc = vc;
|
||||
encoder = vc;
|
||||
}
|
||||
if (!octx->res->frames) {
|
||||
frame->pict_type = AV_PICTURE_TYPE_I;
|
||||
}
|
||||
|
Reference in New Issue
Block a user