[FFmpeg-user] turn PNG to h264 video function
Nemo
377307289 at qq.com
Wed May 27 09:06:55 CEST 2015
I have a funtion to turn PNG to h264, but encode function returns 0, what's going on?
void Png2Video(const char* image_path, const char* video_path)
{
uint8_t *outbuf = NULL, *rgb_buf = NULL;
uint8_t * yuv_buf;
int got_frame = 0, out_size = 0, bufSize = 0, outbuf_size = 100000;
int i = 0, ret = 0;
int got_packet = 0;
FILE *output_file = NULL;
AVCodec *dec = NULL;
AVCodec *enc = NULL;
AVCodecContext *dec_ctx = NULL;
AVCodecContext *enc_ctx = NULL;
AVFormatContext *fmt_ctx = NULL;
AVFrame *rgb_frame = NULL;
AVFrame *yuv_frame = NULL;
AVPacket rgb_packet;
AVPacket yuv_packet;
AVRational rational = {1, 25};
av_init_packet(&rgb_packet);
rgb_packet.data = NULL;
rgb_packet.size = 0;
av_init_packet(&yuv_packet);
yuv_packet.data = NULL;
yuv_packet.size = 0;
av_register_all();
avcodec_register_all();
ret = avformat_open_input(&fmt_ctx, image_path, NULL, NULL);
if(ret < 0)
{
//Cant't open png file
return;
}
avformat_find_stream_info(fmt_ctx, 0);
//dec_ctx = fmt_ctx->streams[0]->codec;
dec = avcodec_find_decoder(fmt_ctx->streams[0]->codec->codec_id);
dec_ctx = avcodec_alloc_context3(dec);
dec_ctx->width = fmt_ctx->streams[0]->codec->width;
dec_ctx->height = fmt_ctx->streams[0]->codec->height;
dec_ctx->pix_fmt = fmt_ctx->streams[0]->codec->pix_fmt;
if(dec->capabilities&CODEC_CAP_TRUNCATED)
dec_ctx->flags|= CODEC_FLAG_TRUNCATED;
ret = avcodec_open2(dec_ctx, dec, NULL); // Open codec(decoder)
if(ret < 0)
{
//Can't find the decoder
return;
}
enc = avcodec_find_encoder(CODEC_ID_H264);//可以换CODEC_ID_MPEG1VIDEO吗
enc_ctx = avcodec_alloc_context3(enc);
enc_ctx->bit_rate = 400000;
enc_ctx->width = dec_ctx->width;
enc_ctx->height = dec_ctx->height;
enc_ctx->time_base = rational;
enc_ctx->gop_size = 10; /* emit one intra rgb_frame every ten frames */
enc_ctx->max_b_frames = 1;
enc_ctx->pix_fmt = PIX_FMT_YUV420P; //encode to YUV
enc_ctx->qmin=1;
enc_ctx->qmax=5;
if(CODEC_ID_H264 == CODEC_ID_H264)
av_opt_set(enc_ctx->priv_data, "preset", "slow", 0);
av_opt_set(enc_ctx->priv_data, "preset", "superfast", 0);
av_opt_set(enc_ctx->priv_data, "tune", "zerolatency", 0);
ret = avcodec_open2(enc_ctx, enc, NULL); // Open codec(encoder)
if(ret < 0)
{
return;
}
rgb_frame = avcodec_alloc_frame();
yuv_frame = avcodec_alloc_frame();
if (!rgb_frame || !yuv_frame)
{
//Can't alloc the input rgb_frame or yuv_frame
return;
}
yuv_frame->width = dec_ctx->width;
yuv_frame->height = dec_ctx->height;
yuv_frame->format = PIX_FMT_YUV420P; //(int)dec_ctx->pix_fmt;
yuv_frame->pts = 0;
int yuv_data_size = av_image_alloc(yuv_frame->data, yuv_frame->linesize, enc_ctx->width, enc_ctx->height, enc_ctx->pix_fmt, 32);
if(fopen_s(&output_file, video_path, "wb") < 0)
{
return;
}
SwsContext * scxt = sws_getContext(dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt, enc_ctx->width, enc_ctx->height, PIX_FMT_YUV420P, SWS_POINT, NULL, NULL, NULL);
while (av_read_frame(fmt_ctx, &rgb_packet) >= 0)
{
if(rgb_packet.stream_index != 0)
continue;
ret = avcodec_decode_video2(dec_ctx, rgb_frame, &got_frame, &rgb_packet);
if (ret > 0 && got_frame != 0)
{
rgb_frame->quality = 4;
sws_scale(scxt, rgb_frame->data, rgb_frame->linesize, 0, rgb_frame->height, yuv_frame->data, yuv_frame->linesize);
//2500 frames, 10s
for(i = 0; i < 2500; i++) {
fflush(stdout);
/* encode the image */
yuv_packet.pts = yuv_packet.dts = yuv_frame->pts;
out_size = avcodec_encode_video2(enc_ctx, &yuv_packet, yuv_frame, &got_packet);
if(out_size > 0 && got_packet != 0)
{
fwrite(yuv_packet.data, 1, yuv_packet.size, output_file);
fflush(output_file);
yuv_packet.data = NULL;
yuv_packet.size = 0;
yuv_frame->pts = i * 1000;
break;
}
}
}
}
fclose(output_file);
free(outbuf);
avcodec_close(enc_ctx);
av_free(enc_ctx);
av_free(rgb_frame);
av_free(yuv_frame);
}
More information about the ffmpeg-user
mailing list