最简单的基于FFmpeg的解码器
生活随笔
收集整理的這篇文章主要介紹了
最简单的基于FFmpeg的解码器
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
參考鏈接:《基于 FFmpeg + SDL 的視頻播放器的制作》課程的視頻_雷霄驊(leixiaohua1020)的專欄-CSDN博客_雷霄驊ffmpeg視頻教程
如有不詳細之處可以觀看雷神視頻講解,相關資源可前往下方鏈接免費下載,如果鏈接失效可直接微博留言(3條消息) 雷霄驊——FFmpeg視頻解碼器-講義文檔類資源-CSDN文庫
?
?
? av_register_all():注冊所有組件。
? avformat_open_input():打開輸入視頻文件。
? avformat_find_stream_info():獲取視頻文件信息。
? avcodec_find_decoder():查找解碼器。
? avcodec_open2():打開解碼器。
? av_read_frame():從輸入文件讀取一幀壓縮數據。
? avcodec_decode_video2():解碼一幀壓縮數據。
? avcodec_close():關閉解碼器。
? avformat_close_input():關閉輸入視頻文件。
先附上相關代碼以及注釋:
#include <stdio.h> #include <iostream> #include <fstream> using namespace std;#define __STDC_CONSTANT_MACROSextern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libswscale/swscale.h" };int main(int argc, char* argv[]) {AVFormatContext *pFormatCtx; //定義結構體指針int i, videoindex;AVCodecContext *pCodecCtx;AVCodec *pCodec;AVFrame *pFrame,*pFrameYUV;uint8_t *out_buffer;AVPacket *packet;int y_size;int ret, got_picture;struct SwsContext *img_convert_ctx;//輸入文件路徑char filepath[]="Titanic.ts";int frame_cnt;av_register_all(); //初始化組件avformat_network_init(); //初始化網絡連接pFormatCtx = avformat_alloc_context();//打開輸入視頻文件if(avformat_open_input(&pFormatCtx,filepath,NULL,NULL)!=0){printf("Couldn't open input stream.\n");return -1;}//獲取流信息if(avformat_find_stream_info(pFormatCtx,NULL)<0){printf("Couldn't find stream information.\n");return -1;}videoindex=-1;for(i=0; i<pFormatCtx->nb_streams; i++) //nb_streams:輸入視頻的AVStream 個數if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){ //streams:輸入視頻的AVStream []數組videoindex=i; //判斷文件是視頻流還是音頻流,把其中的視頻流獲取出來break;}if(videoindex==-1){printf("Didn't find a video stream.\n");return -1;}pCodecCtx=pFormatCtx->streams[videoindex]->codec; pCodec=avcodec_find_decoder(pCodecCtx->codec_id); //獲取解碼器if(pCodec==NULL){printf("Codec not found.\n");return -1;}if(avcodec_open2(pCodecCtx, pCodec,NULL)<0){ //打開解碼器 printf("Could not open codec.\n");return -1;}/** 在此處添加輸出視頻信息的代碼* 取自于pFormatCtx,使用fprintf()*///FILE* fp = fopen("info.txt", "wb+");ofstream fout("info.txt");fout << "時長為:" << pFormatCtx->duration << " 毫秒" << endl;fout << "封裝格式為: " << pFormatCtx->iformat->name <<endl;fout << "視頻幀的寬為:" << pCodecCtx->width << " 視頻幀的高為: "<< pCodecCtx->height <<endl;fout << "視頻幀的寬為:" << pFormatCtx->streams[videoindex]->codec->width << " 視頻幀的高為: " << pFormatCtx->streams[videoindex]->codec->height << endl;fout.close();//fclose(fp);//printf("時長:%d", pFormatCtx->duration);pFrame=av_frame_alloc();pFrameYUV=av_frame_alloc();out_buffer=(uint8_t *)av_malloc(avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);packet=(AVPacket *)av_malloc(sizeof(AVPacket));//Output Info-----------------------------printf("--------------- File Information ----------------\n");av_dump_format(pFormatCtx,0,filepath,0);printf("-------------------------------------------------\n");img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); FILE* fp_264 = fopen("test264.h264", "wb+");FILE* fp_yuv = fopen("testyuv.yuv", "wb+");frame_cnt=0;while(av_read_frame(pFormatCtx, packet)>=0){ //讀取幀if(packet->stream_index==videoindex){ //判斷是不是視頻幀/** 在此處添加輸出H264碼流的代碼* 取自于packet,使用fwrite()*/fwrite(packet->data, 1, packet->size, fp_264);ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);if(ret < 0){printf("Decode Error.\n");return -1;}if(got_picture){sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);printf("Decoded frame index: %d\n",frame_cnt);/** 在此處添加輸出YUV的代碼* 取自于pFrameYUV,使用fwrite()*/fwrite(pFrameYUV->data[0], 1, (pCodecCtx->width)*(pCodecCtx->height), fp_yuv);fwrite(pFrameYUV->data[1], 1, (pCodecCtx->width) * (pCodecCtx->height) / 4, fp_yuv);fwrite(pFrameYUV->data[2], 1, (pCodecCtx->width) * (pCodecCtx->height) / 4, fp_yuv);frame_cnt++;}}av_free_packet(packet);}fclose(fp_264);fclose(fp_yuv);sws_freeContext(img_convert_ctx);av_frame_free(&pFrameYUV);av_frame_free(&pFrame);avcodec_close(pCodecCtx);avformat_close_input(&pFormatCtx);return 0; }總結
以上是生活随笔為你收集整理的最简单的基于FFmpeg的解码器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python qrcode生成二维码
- 下一篇: 2022年最新《谷粒学院开发教程》:5