ffmpeg 解码视频(h264、mpeg2)输出yuv420p文件
生活随笔
收集整理的這篇文章主要介紹了
ffmpeg 解码视频(h264、mpeg2)输出yuv420p文件
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
ffmpeg 解碼視頻(h264、mpeg2)輸出yuv420p文件
播放yuv可以參考:ffplay -pixel_format yuv420p -video_size 768x320 -framerate 25 out.yuv
main.c
#include <stdio.h> #include <stdlib.h> #include <string.h>#include <libavutil/frame.h> #include <libavutil/mem.h>#include <libavcodec/avcodec.h>#define VIDEO_INBUF_SIZE 10240 #define VIDEO_REFILL_THRESH 4096static void decode(AVCodecContext* dec_ctx, AVPacket* pkt, AVFrame* frame, FILE* outfile) {int ret;//發一幀數據進行解碼int send_ret = 1;do{ret = avcodec_send_packet(dec_ctx, pkt);if(ret == AVERROR(EAGAIN))//AVERROR(EAGAIN) 傳入失敗,表示先要receive frame再重新send packet{send_ret = 0;printf("avcodec_send_packet ret == AVERROR(EAGAIN)\n");}else if(ret < 0){printf("avcodec_send_packet ret < 0\n");return;}while(ret >= 0){//調用avcodec_receive_frame會在內部首先調用av_frame_unref來釋放frame本來的數據//就是這次調用會將上次調用返回的frame數據釋放ret = avcodec_receive_frame(dec_ctx, frame);if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)return;else if(ret < 0){printf("avcodec_receive_frame = ret < 0\n");return;}//在第一幀的時候輸出一下音頻信息static int print_info = 1;if(print_info){print_info = 0;printf("width : %uHz\n", frame->width);printf("height : %u\n", frame->height);printf("fformat : %u\n", frame->format);}//寫入h264文件,yuv420p//yuv420格式 :yyyyyyy......uuuu.....vvvvv.......fwrite(frame->data[0], 1, frame->width * frame->height, outfile);//y分量fwrite(frame->data[1], 1, (frame->width) * (frame->height) / 4, outfile);//u分量fwrite(frame->data[2], 1, (frame->width) * (frame->height) / 4, outfile);//v分量}}while(!send_ret); }#define H264 0 int main() {printf("Hello video decoder!\n");const char* outfilename = "out.yuv";#if H264const char* filename = "test.h264"; #elseconst char* filename = "test.mpeg2"; #endifconst AVCodec* codec = NULL;AVCodecContext* codec_ctx = NULL;AVCodecParserContext* parser = NULL;int len = 0;int ret = 0;FILE* infile = NULL;FILE* outfile = NULL;// AV_INPUT_BUFFER_PADDING_SIZE 在輸入比特流結尾的要求附加分配字節的數量上進行解碼//具體什么影響不知道uint8_t inbuf[VIDEO_INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];uint8_t* data = NULL;size_t data_size = 0;AVPacket* pkt = NULL;AVFrame* de_frame = NULL;//申請AVPacket本身的內存pkt = av_packet_alloc();enum AVCodecID video_codec_id = AV_CODEC_ID_NONE;if(strstr(filename, ".h264") != NULL){video_codec_id = AV_CODEC_ID_H264;}else if(strstr(filename, ".mpeg2") != NULL){video_codec_id = AV_CODEC_ID_MPEG2VIDEO;}else{printf("video_codec_id = AV_CODEC_ID_NONE\n");return 0;}//查找解碼器codec = avcodec_find_decoder(video_codec_id);if(!codec){printf("Codec not find!\n");return 0;}//根據解碼器ID獲取裸流的解析器printf("video decoder end!\n");parser = av_parser_init(codec->id);if(!parser){printf("Parser not find!\n");return 0;}//分配codec使用的上下文codec_ctx = avcodec_alloc_context3(codec);if(!codec_ctx){printf("avcodec_alloc_context3 failed!\n");return 0;}//將解碼器和解碼使用的上下文關聯if(avcodec_open2(codec_ctx, codec, NULL) < 0){printf("avcodec_open2 failed!\n");return 0;}//打開文件infile = fopen(filename, "rb");if(!infile){printf("infile fopen failed!\n");return 0;}//輸出文件outfile = fopen(outfilename, "wb");if(!outfile){printf("outfilie fopen failed!\n");return 0;}int file_end = 0;//讀取文件 開始解碼data = inbuf;data_size = fread(inbuf, 1, VIDEO_INBUF_SIZE, infile);de_frame = av_frame_alloc();while (data_size > 0){//獲取傳入到avcodec_send_packet一個packet的數據量//(一幀)ret = av_parser_parse2(parser, codec_ctx, &pkt->data, &pkt->size,data, data_size,AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);if(ret < 0){printf("av_parser_parser2 Error!\n");return 0;}//使用了多少數據做一個偏移data += ret;data_size -= ret;if(pkt->size)decode(codec_ctx, pkt, de_frame, outfile);//如果當前緩沖區中數據少于VIDEO_REFILL_THRESH就再讀//避免多次讀文件if((data_size < VIDEO_REFILL_THRESH) && !file_end){//剩余數據移動緩沖區前memmove(inbuf, data, data_size);data = inbuf;//跨過已有數據存儲len = fread(data + data_size, 1, VIDEO_INBUF_SIZE - data_size, infile);if(len > 0)data_size += len;else if(len == 0){file_end = 1;printf("file end!\n");}}}//沖刷解碼器pkt->data = NULL;pkt->size = 0;decode(codec_ctx, pkt, de_frame, outfile);fclose(infile);fclose(outfile);avcodec_free_context(&codec_ctx);av_parser_close(parser);av_frame_free(&de_frame);av_packet_free(&pkt);printf("video decoder end!\n");return 0; } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的ffmpeg 解码视频(h264、mpeg2)输出yuv420p文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DNF柔道怎么连招?
- 下一篇: 女人难嫁剧情介绍