我正在尝试将视频从1080p扩展到480p。为此,我将swscaler context设置为:
encoder_sc->sws_ctx = sws_getContext(1920, 1080,
AV_PIX_FMT_YUV420P,
854, 480, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL );
但是,当我调用缩放框架函数时,
sws_scale_frame(encoder->sws_ctx, input_frame, input_frame);
但是,当我这样做时,我得到错误Slice parameter 0, 1080 are in valid
。我对FFMPEG和一般的视频处理非常陌生。我在寻找的时候找不到任何解决办法。任何帮助都非常感谢。
编辑:我包括整个源代码,因为我似乎无法解决这个问题。
typedef struct StreamingContext{
AVFormatContext* avfc;
AVCodec *video_avc;
AVCodec *audio_avc;
AVStream *video_avs;
AVStream *audio_avs;
AVCodecContext *video_avcc;
AVCodecContext *audio_avcc;
int video_index;
int audio_index;
char* filename;
struct SwsContext *sws_ctx;
}StreamingContext;
typedef struct StreamingParams{
char copy_video;
char copy_audio;
char *output_extension;
char *muxer_opt_key;
char *muxer_opt_value;
char *video_codec;
char *audio_codec;
char *codec_priv_key;
char *codec_priv_value;
}StreamingParams;
int prepare_video_encoder(StreamingContext *encoder_sc, AVCodecContext *decoder_ctx, AVRational input_framerate,
StreamingParams sp)
{
encoder_sc->video_avs = avformat_new_stream(encoder_sc->avfc, NULL);
encoder_sc->video_avc = avcodec_find_encoder_by_name(sp.video_codec);
if (!encoder_sc->video_avc)
{
logging("Cannot find the Codec.");
return -1;
}
encoder_sc->video_avcc = avcodec_alloc_context3(encoder_sc->video_avc);
if (!encoder_sc->video_avcc)
{
logging("Could not allocate memory for Codec Context.");
return -1;
}
av_opt_set(encoder_sc->video_avcc->priv_data, "preset", "fast", 0);
if (sp.codec_priv_key && sp.codec_priv_value)
av_opt_set(encoder_sc->video_avcc->priv_data, sp.codec_priv_key, sp.codec_priv_value, 0);
encoder_sc->video_avcc->height = decoder_ctx->height;
encoder_sc->video_avcc->width = decoder_ctx->width;
encoder_sc->video_avcc->sample_aspect_ratio = decoder_ctx->sample_aspect_ratio;
if (encoder_sc->video_avc->pix_fmts)
encoder_sc->video_avcc->pix_fmt = encoder_sc->video_avc->pix_fmts[0];
else
encoder_sc->video_avcc->pix_fmt = decoder_ctx->pix_fmt;
encoder_sc->video_avcc->bit_rate = 2 * 1000 * 1000;
encoder_sc->video_avcc->rc_buffer_size = 4 * 1000 * 1000;
encoder_sc->video_avcc->rc_max_rate = 2 * 1000 * 1000;
encoder_sc->video_avcc->rc_min_rate = 2.5 * 1000 * 1000;
encoder_sc->video_avcc->time_base = av_inv_q(input_framerate);
encoder_sc->video_avs->time_base = encoder_sc->video_avcc->time_base;
//Creating Scaling Context
encoder_sc->sws_ctx = sws_getContext(1920, 1080,
decoder_ctx->pix_fmt,
854, 480, encoder_sc->video_avcc->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL );
if (!encoder_sc->sws_ctx){logging("Cannot Create Scaling Context."); return -1;}
if (avcodec_open2(encoder_sc->video_avcc, encoder_sc->video_avc, NULL) < 0)
{
logging("Could not open the Codec.");
return -1;
}
avcodec_parameters_from_context(encoder_sc->video_avs->codecpar, encoder_sc->video_avcc);
return 0;
}
int transcode_video(StreamingContext *decoder, StreamingContext *encoder, AVPacket *input_packet, AVFrame *input_frame, AVFrame *scaled_frame)
{
int response = avcodec_send_packet(decoder->video_avcc, input_packet);
if (response < 0)
{
logging("Error while sending the Packet to Decoder: %s", av_err2str(response));
return response;
}
while (response >= 0)
{
response = avcodec_receive_frame(decoder->video_avcc, input_frame);
if (response == AVERROR(EAGAIN) || response == AVERROR_EOF)
{
break;
}
else if (response < 0)
{
logging("Error while receiving frame from Decoder: %s", av_err2str(response));
return response;
}
if (response >= 0)
{
scaled_frame->format = encoder->video_avcc->pix_fmt;
scaled_frame->width = 854;
scaled_frame->height = 480;
sws_scale_frame(encoder->sws_ctx, scaled_frame, input_frame);
//ERROR is in the scaled_frame
if (encode_video(decoder, encoder, scaled_frame))
return -1;
}
av_frame_unref(input_frame);
}
return 0;
}
1条答案
按热度按时间qyuhtwio1#
在你发布的一小段代码中,我们可以看到有一个问题。
使用
input_frame, input_frame
而不是output_frame, input_frame
是问题所在。将
sws_scale_frame(encoder->sws_ctx, input_frame, input_frame);
替换为:执行
sws_scale_frame
时,该函数验证输入和输出的尺寸和格式是否与sws_getContext
中定义的尺寸和格式匹配。在我们的案例中:
输入的宽度和高度必须为1920和1080。
宽度和高度输出必须为854和480。
当尺寸不匹配时,函数失败并返回错误(返回负值)。
在我们的例子中,输出的预期高度是
854
,但帧的给定高度是1080
。我不知道这是不是唯一的问题...
我创建了一个完整的可重复的示例来演示
sws_scale_frame
的用法-缩放单个帧。代码示例:
从YUV 420 p转换为PNG图像后的输出图像(缩小):