[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