网站开发动态,天河商城型网站建设,龙之向导外贸网站 网络服务,宁波外贸公司一览表使用FFmpeg库把YUV420P文件编码为H264文件#xff0c;FFmpeg版本为4.4.2-0。
需要yuv测试文件的#xff0c;可以从我上传的MP4文件中用ffmpeg提取#xff0c;命令如下#xff1a;
ffmpeg -i input.mp4 -pix_fmt yuv420p output.yuv 代码如下#xff1a;…使用FFmpeg库把YUV420P文件编码为H264文件FFmpeg版本为4.4.2-0。
需要yuv测试文件的可以从我上传的MP4文件中用ffmpeg提取命令如下
ffmpeg -i input.mp4 -pix_fmt yuv420p output.yuv 代码如下
#include stdio.h
#include stdlib.h
#include string.h
#include libavcodec/avcodec.h
#include libavformat/avformat.h
#include libavutil/opt.h
#include libavutil/mem.h
#include libavutil/imgutils.h
#include libswscale/swscale.hint main(int argc, char *argv[])
{int ret -1;int frame_index 0;const char *input_file argv[1];const char *output_file argv[2];FILE *input_yuv NULL;AVFormatContext *format_context NULL;AVCodecContext *codec_context NULL;AVStream *stream NULL;AVCodec *codec NULL;AVFrame *frame NULL;AVPacket *packet NULL;const AVOutputFormat *ofmt NULL;int in_width 1280; // 输入YUV文件的宽度int in_height 720; // 输入YUV文件的高度enum AVPixelFormat in_pix_fmt AV_PIX_FMT_YUV420P; // 输入YUV文件的像素格式int frame_rate 24; // 输出视频帧率if (argc 3){fprintf(stderr, Usage: %s input file output file\n, argv[0]);return -1;}input_yuv fopen(input_file, rb);if (!input_yuv){fprintf(stderr, open input file failed\n);goto end;}// 分配输出格式上下文avformat_alloc_output_context2(format_context, NULL, NULL, output_file);if (!format_context){fprintf(stderr, avformat_alloc_output_context2 failed\n);goto end;}ofmt format_context-oformat;// 查找编码器codec avcodec_find_encoder(AV_CODEC_ID_H264);if (!codec){fprintf(stderr, Codec not found\n);goto end;}printf(codec name: %s\n, codec-name);// 创建新的视频流stream avformat_new_stream(format_context, NULL);if (!stream){fprintf(stderr, avformat_new_stream failed\n);goto end;}// 分配编码器上下文codec_context avcodec_alloc_context3(codec);if (!codec_context){fprintf(stderr, avcodec_alloc_context3 failed\n);goto end;}/* 设置编码器参数 */codec_context-codec_id AV_CODEC_ID_H264;codec_context-codec_type AVMEDIA_TYPE_VIDEO;codec_context-pix_fmt AV_PIX_FMT_YUV420P;codec_context-width in_width;codec_context-height in_height;codec_context-time_base (AVRational){1, frame_rate}; // 设置时间基codec_context-framerate (AVRational){frame_rate, 1}; // 设置帧率codec_context-bit_rate 1456 * 1000; // 设置比特率codec_context-gop_size frame_rate; // 设置GOP大小codec_context-max_b_frames 1; // 设置最大B帧数不需要B帧时设置为0av_opt_set(codec_context-priv_data, profile, main, 0); // 设置h264画质级别// 打开编码器if (avcodec_open2(codec_context, codec, NULL) 0){fprintf(stderr, avcodec_open2 failed\n);goto end;}// 将编码器参数复制到流int result avcodec_parameters_from_context(stream-codecpar, codec_context);if (result 0){fprintf(stderr, avcodec_parameters_from_context failed\n);goto end;}// 打开输出文件if (!(ofmt-flags AVFMT_NOFILE)) // 检查输出格式是否需要文件存储{result avio_open(format_context-pb, output_file, AVIO_FLAG_WRITE);if (result 0){fprintf(stderr, open output file failed\n);goto end;}}// 写文件头result avformat_write_header(format_context, NULL);if (result 0){fprintf(stderr, avformat_write_header failed\n);goto end;}frame av_frame_alloc();packet av_packet_alloc();if (!frame || !packet){fprintf(stderr, allocate frame or packet failed\n);goto end;}// 设置帧参数frame-format codec_context-pix_fmt;frame-width codec_context-width;frame-height codec_context-height;// 分配帧数据缓冲区result av_frame_get_buffer(frame, 0);if (result 0){fprintf(stderr, av_frame_get_buffer failed\n);goto end;}// 计算输入缓冲区大小int input_buffer_size av_image_get_buffer_size(in_pix_fmt, in_width, in_height, 1);uint8_t *input_buffer (uint8_t *)av_malloc(input_buffer_size);if (!input_buffer){fprintf(stderr, av_malloc failed\n);goto end;}// 编码循环while (1){// 读取YUV数据到缓冲区result fread(input_buffer, 1, input_buffer_size, input_yuv);if (result 0){break;}// 填充帧数据av_image_fill_arrays(frame-data, frame-linesize, input_buffer, in_pix_fmt, in_width, in_height, 1);frame-pts frame_index;frame_index;// 发送帧到编码器result avcodec_send_frame(codec_context, frame);if (result 0){fprintf(stderr, avcodec_send_frame error (errmsg %s)\n, av_err2str(result));goto end;}// 接收编码后的数据包while (result 0){result avcodec_receive_packet(codec_context, packet);if (result AVERROR(EAGAIN) || result AVERROR_EOF){break;}else if (result 0){fprintf(stderr, avcodec_receive_packet error (errmsg %s)\n, av_err2str(result));goto end;}packet-stream_index stream-index;// 将时间戳从编码器时间基转换到流时间基av_packet_rescale_ts(packet, codec_context-time_base, stream-time_base);// 写数据包到输出文件result av_interleaved_write_frame(format_context, packet);if (result 0){fprintf(stderr, av_interleaved_write_frame failed\n);av_packet_unref(packet);goto end;}av_packet_unref(packet);}}av_free(input_buffer);// 发送NULL帧到编码器刷新编码器内部缓冲区result avcodec_send_frame(codec_context, NULL);while (result 0){result avcodec_receive_packet(codec_context, packet);if (result AVERROR_EOF){break;}else if (result 0){fprintf(stderr, avcodec_receive_packet error (errmsg %s)\n, av_err2str(result));goto end;}packet-stream_index stream-index;av_packet_rescale_ts(packet, codec_context-time_base, stream-time_base);result av_interleaved_write_frame(format_context, packet);if (result 0){fprintf(stderr, av_interleaved_write_frame failed\n);av_packet_unref(packet);goto end;}av_packet_unref(packet);}// 写文件尾av_write_trailer(format_context);ret 0;end:if (frame)av_frame_free(frame);if (packet)av_packet_free(packet);if (codec_context)avcodec_free_context(codec_context);if (ofmt !(ofmt-flags AVFMT_NOFILE))avio_close(format_context-pb);if (format_context)avformat_free_context(format_context);if (input_yuv)fclose(input_yuv);return ret;
}