FFmpeg进阶:编码YUV视频数据
生活随笔
收集整理的這篇文章主要介紹了
FFmpeg进阶:编码YUV视频数据
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
視頻流解碼之后的YUV數據是視頻的原始數據,只包含對應的像素信息,不包含圖像格式信息。在處理和存儲原始的YUV數據的時候,我們一般會對YUV數據進行編碼壓縮。這里就介紹一下YUV數據編碼壓縮的流程。
編碼YUV數據的時候,我們需要指定YUV數據的格式信息,包括:像素分辨率(width,height)、像素格式(pix_fmt)、視頻的幀率(fps)、視頻的碼率(bit_rate)。對應的參考demo如下:
#define _CRT_SECURE_NO_WARNINGSextern "C" { #include <libavutil/imgutils.h> #include <libavutil/samplefmt.h> #include <libavutil/timestamp.h> #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> }int main(int argc, char** argv) {//輸入輸出路徑char* output_path = "./output.mp4";char* input_path = "./input.yuv";//幀率int fps = 24;//視頻寬高int width = 1920;int height = 1080;//輸出編碼方式AVCodecID video_encode_id = AV_CODEC_ID_MPEG4;//視頻像素格式AVPixelFormat pix_fmt = AV_PIX_FMT_YUV420P;//視頻的碼率int bit_rate = 2181017 * 3;//初始化輸出上下文int start_time = clock();AVFormatContext* avformat_context = NULL;avformat_alloc_output_context2(&avformat_context, NULL, NULL, output_path);if (avio_open(&avformat_context->pb, output_path, AVIO_FLAG_WRITE) < 0) {return;}//創建編碼器,指定參數AVCodec * codec = avcodec_find_encoder(video_encode_id);AVCodecContext *avcodec_context = avcodec_alloc_context3(codec);avcodec_context->time_base.den = fps;avcodec_context->time_base.num = 1;avcodec_context->codec_id = video_encode_id;avcodec_context->codec_type = AVMEDIA_TYPE_VIDEO;avcodec_context->pix_fmt = pix_fmt;avcodec_context->width = width;avcodec_context->height = height;//創建輸出視頻流AVStream* avvideo_stream = avformat_new_stream(avformat_context, NULL);avvideo_stream->codec = avcodec_context;avvideo_stream->time_base = avcodec_context->time_base;avvideo_stream->codec->codec_tag = 0;avvideo_stream->codecpar->bit_rate = bit_rate;//打開編碼器int ret = avcodec_open2(avcodec_context, codec, NULL);if (ret) {return;}//輸出文件頭int avformat_write_header_result = avformat_write_header(avformat_context, NULL);if (avformat_write_header_result != AVSTREAM_INIT_IN_WRITE_HEADER) {return;}//分配圖像內存int buffer_size = av_image_get_buffer_size(avcodec_context->pix_fmt,avcodec_context->width,avcodec_context->height,1);uint8_t *out_buffer = (uint8_t *)av_malloc(buffer_size);//創建數據幀AVFrame *frame = av_frame_alloc();av_image_fill_arrays(frame->data,frame->linesize,out_buffer,avcodec_context->pix_fmt,avcodec_context->width,avcodec_context->height,1);frame->format = pix_fmt;frame->width = width;frame->height = height;AVPacket *av_packet = av_packet_alloc();av_init_packet(av_packet);uint8_t * file_buffer = (uint8_t *)av_malloc(width * height * 3 / 2);FILE *in_file = fopen(input_path, "rb");int pts = 0;while (1) {//讀取YUV420P數據if (fread(file_buffer, 1, width * height * 3 / 2, in_file) <= 0) {break;}else if (feof(in_file)) {break;}//封裝yuv幀數據frame->data[0] = file_buffer; //Y起始數據索引frame->data[1] = file_buffer + width * height; //U數據起始索引frame->data[2] = file_buffer + width * height * 5 / 4;//V起始數據索引frame->linesize[0] = width; //Y數據的行寬frame->linesize[1] = width / 2;//U數據的行寬frame->linesize[2] = width / 2;//V數據的行寬frame->pts = pts;pts++;//對原始YUV數據進行編碼avcodec_send_frame(avcodec_context, frame);while (1) {int ret = avcodec_receive_packet(avcodec_context, av_packet);if (ret) {av_packet_unref(av_packet);break;}av_packet_rescale_ts(av_packet, avcodec_context->time_base, avvideo_stream->time_base);av_packet->stream_index = avvideo_stream->index;//與av_write_frame的區別是,將對packet進行緩存和pts檢查//將編碼之后的數據幀寫入到文件中av_interleaved_write_frame(avformat_context, av_packet);}}//解析剩余的數據幀avcodec_send_frame(avcodec_context, NULL);while (1) {int ret = avcodec_receive_packet(avcodec_context, av_packet);if (ret) {av_packet_unref(av_packet);break;}av_packet_rescale_ts(av_packet, avcodec_context->time_base, avvideo_stream->time_base);av_packet->stream_index = avvideo_stream->index;av_interleaved_write_frame(avformat_context, av_packet);}//關閉文件fclose(in_file);//輸出耗時int end_time = clock();printf("encode file cost:%d", end_time - start_time);avcodec_close(avcodec_context);//清理分配的內存av_free(frame);av_free(out_buffer);av_write_trailer(avformat_context);avio_close(avformat_context->pb);avformat_free_context(avformat_context);}總結
以上是生活随笔為你收集整理的FFmpeg进阶:编码YUV视频数据的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用python实现深度神经网络 4
- 下一篇: PMO和PM如何实现从战略解码到项目执行