日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【开源项目】使用FFMPEG解析H264编码为YUV格式

發布時間:2023/12/3 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【开源项目】使用FFMPEG解析H264编码为YUV格式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

頭文件

#pragma once#ifndef _VIDEO_DECODING_HEADER_ #define _VIDEO_DECODING_HEADER_#define INBUF_SIZE 4096 #define AUDIO_INBUF_SIZE 20480 #define AUDIO_REFILL_THRESH 4096extern "C" { #include "libavutil/opt.h" #include "libavcodec/avcodec.h" #include "libavutil/channel_layout.h" #include "libavutil/common.h" #include "libavutil/imgutils.h" #include "libavutil/mathematics.h" #include "libavutil/samplefmt.h" }/************************************************* Struct: CodecCtx Description: FFMpeg編解碼器上下文 *************************************************/ typedef struct {AVCodec *pCodec; //編解碼器實例指針AVCodecContext *pCodecContext; //編解碼器上下文,指定了編解碼的參數AVCodecParserContext *pCodecParserCtx; //編解碼解析器,從碼流中截取完整的一個NAL Unit數據AVFrame *frame; //封裝圖像對象指針AVPacket pkt; //封裝碼流對象實例 } CodecCtx;#endif

cpp文件

/************* 解碼主要步驟: 1.解析輸入參數,獲取待解碼的碼流數據 2.初始化相應的FFMpeg結構 3.循環讀取并解析輸入碼流數據--由2進制碼流解析為FFMpeg可以處理的包數據 4.解碼解析出的包為像素數據 5.寫出像素數據 6.收尾工作 *************/#include<stdio.h> #include<stdint.h> #include"VideoDecodingHeader.h"#define INBUF_SIZE 4096 //接受區域大小FILE* pFin = NULL; FILE* pFout = NULL;AVCodec* pCodec = NULL; AVCodecContext* pCodecContext = NULL; AVCodecParserContext* pCodecParserCtx = NULL; //碼流解碼供解碼器使用的包AVFrame* frame = NULL; AVPacket pkt;static int open_input_output_file(char **argv) {const char* inputFileName = argv[1];const char* outputFileName = argv[2];//fopen_s 以二進制只讀的方式打開inputFileName,返回FILE指針fopen_s(&pFin, inputFileName, "rb+");if (!pFin){printf("Error: open input file failed.\n");return -1;}fopen_s(&pFout, outputFileName, "wb+");if (!pFout){printf("Error: open input file failed.\n");return -1;}return 0; } //打開解碼器且初始化 static int open_decoder() {//注冊組件avcodec_register_all();//初始化最后輸出的pktav_init_packet(&pkt);//查找解碼器pCodec = avcodec_find_decoder(AV_CODEC_ID_H264);if (!pCodec){return -1;}pCodecContext = avcodec_alloc_context3(pCodec);if (!pCodecContext){return -1;}if (pCodec->capabilities & AV_CODEC_CAP_TRUNCATED){pCodecContext->flags |= AV_CODEC_CAP_TRUNCATED;}//初始化解析器pCodecParserCtx = av_parser_init(AV_CODEC_ID_H264);if (!pCodecParserCtx){printf("Error:alloc parser failed.\n");return -1;}//打開解碼器if (avcodec_open2(pCodecContext, pCodec, NULL) < 0){printf("Error:open condec failed.\n");return -1;}//開辟frame空間frame = av_frame_alloc();if (!frame){printf("Error:alloc frame failed.\n");return -1;}return 0;} //寫出YUV數據 static void write_out_yuv_frame(AVFrame *frame) {uint8_t **pBuf = frame->data;//保存地址int* pStride = frame->linesize;//保存位寬for (int color_idx = 0; color_idx < 3; color_idx++){int nWidth = color_idx == 0 ? frame->width : frame->width / 2;int nHeight = color_idx == 0 ? frame->height : frame->height / 2;for (int idx = 0; idx < nHeight; idx++){fwrite(pBuf[color_idx], 1, nWidth, pFout);pBuf[color_idx] += pStride[color_idx];}fflush(pFout);} } //收尾工作 static void Close() {fclose(pFin);fclose(pFout);avcodec_close(pCodecContext);av_free(pCodecContext);av_frame_free(&frame);}int main(int argc, char **argv) {//從輸入文件讀取碼流數據保存到的緩存位置uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];if (open_input_output_file(argv) < 0){return -1;}else{printf("Open input/ouput file succeed\n");}if (open_decoder() < 0){return -1;}else{printf("Open decoder file succeed\n");}//解碼循環int uDataSize = 0, len = 0;int got_frame = 0;uint8_t* pDataPtr = NULL;while (true){uDataSize = fread_s(inbuf, INBUF_SIZE, 1, INBUF_SIZE, pFin);if (uDataSize == 0){break;}pDataPtr = inbuf;while (uDataSize>0){len = av_parser_parse2(pCodecParserCtx, pCodecContext,&pkt.data, &pkt.size,pDataPtr, uDataSize, AV_NOPTS_VALUE, AV_NOPTS_VALUE, AV_NOPTS_VALUE);pDataPtr += len;uDataSize -= len;//pkt.size==0沒有解析完if (pkt.size == 0){continue;}//!=0成功解析出一個packet的碼流printf("Parse 1 packet.\n");int ret = avcodec_decode_video2(pCodecContext, frame, &got_frame, &pkt);if (ret < 0){printf("Error: decode failed.\n");return -1;}if (got_frame){printf("Decoded 1 frame OK! Width x Height: (%d x %d)\n", frame->width, frame->height);write_out_yuv_frame(frame);}else{break;}}}pkt.data = NULL;pkt.size = 0;while (true){int ret = avcodec_decode_video2(pCodecContext, frame, &got_frame, &pkt);if (ret < 0){printf("Error: decode failed.\n");return -1;}if (got_frame){printf("Flush Decoded 1 frame OK! Width x Height: (%d x %d)\n", frame->width, frame->height);write_out_yuv_frame(frame);}}Close();return 0; }

?

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的【开源项目】使用FFMPEG解析H264编码为YUV格式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。