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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

嵌入式linux------ffmpeg移植 解码H264(am335x解码H264到yuv420并通过SDL显示)

發(fā)布時間:2025/6/15 linux 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 嵌入式linux------ffmpeg移植 解码H264(am335x解码H264到yuv420并通过SDL显示) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
/* 編譯命令:arm-linux-gcc -o show2642 264showyuv2.c -I/usr/local/ffmpeg_arm/include/ -L/usr/local/ffmpeg_arm/lib/ -lswresample -lavformat -lavutil -lavcodec -lswscale -lx264 libSDL.a */ #include "stdio.h" #include "stdlib.h"#include "libavformat/avformat.h" #include "libavdevice/avdevice.h" #include "libswresample/swresample.h" #include "libavutil/opt.h" #include "libavutil/channel_layout.h" #include "libavutil/parseutils.h" #include "libavutil/samplefmt.h" #include "libavutil/fifo.h" #include "libavutil/intreadwrite.h" #include "libavutil/dict.h" #include "libavutil/mathematics.h" #include "libavutil/pixdesc.h" #include "libavutil/avstring.h" #include "libavutil/imgutils.h" #include "libavutil/timestamp.h" #include "libavutil/bprint.h" #include "libavutil/time.h" #include "libavutil/threadmessage.h" #include "/usr/local/ffmpeg_arm/include/SDL/SDL.h"#include "libavfilter/avcodec.h" #include "libavcodec/avcodec.h"#if HAVE_SYS_RESOURCE_H #include <sys/time.h> #include <sys/types.h> #include <sys/resource.h> #elif HAVE_GETPROCESSTIMES #include <windows.h> #endif #if HAVE_GETPROCESSMEMORYINFO #include <windows.h> #include <psapi.h> #endif#if HAVE_SYS_SELECT_H #include <sys/select.h> #endif#if HAVE_TERMIOS_H #include <fcntl.h> #include <sys/ioctl.h> #include <sys/time.h> #include <termios.h> #elif HAVE_KBHIT #include <conio.h> #endif#if HAVE_PTHREADS #include <pthread.h> #endif#include <time.h>#include "libavutil/avassert.h"#define MAX_LEN 1024 * 50此方法參考官網(wǎng)的樣例 static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize,FILE *f) {// FILE *f;int i;// f = fopen(filename,"w");// fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);for (i = 0; i < ysize; i++)fwrite(buf + i * wrap, 1, xsize, f);// fclose(f); }int main() {//以下初始化h264解碼庫//avcodec_init();int w = 720;int h = 576,retu;SDL_Rect rect;av_register_all();AVFrame *pFrame_ = NULL;/* find the video encoder */AVCodec *videoCodec = avcodec_find_decoder(CODEC_ID_H264);//得到264的解碼器類if(!videoCodec){printf("avcodec_find_decoder error\n");return -1;}AVCodecParserContext *avParserContext = av_parser_init(CODEC_ID_H264);//得到解析幀類。主要用于后面的幀頭查找if(!avParserContext){printf("av_parser_init error\n");return -1;}AVCodecContext *codec_ = avcodec_alloc_context3(videoCodec);//解碼會話層if(!codec_){printf("avcodec_alloc_context3 error\n");return -1;}//初始化參數(shù),以下的參數(shù)應(yīng)該由詳細的業(yè)務(wù)決定codec_->time_base.num = 1;codec_->frame_number = 1; //每包一個視頻幀codec_->codec_type = AVMEDIA_TYPE_VIDEO;codec_->bit_rate = 0;codec_->time_base.den = 25;//幀率codec_->width = 720;//視頻寬codec_->height = 576;//視頻高if(avcodec_open2(codec_, videoCodec, NULL) >= 0)//打開解碼器{pFrame_ = avcodec_alloc_frame();// Allocate video frame 成功打開解碼器后, 此時能夠分配幀內(nèi)存, 當然你也能夠在后面每次都分配、釋放, 在此我省功夫, 僅僅在開始分配一次if (!pFrame_) {fprintf(stderr, "Could not allocate video frame\n");exit(1);}}else{printf("avcodec_open2 error\n");return -1;}AVPacket packet = {0};int dwBufsize = 10;int frameFinished = dwBufsize;//這個是隨便填入數(shù)字,沒什么作用av_init_packet(&packet);packet.data = NULL;//這里填入一個指向完整H264數(shù)據(jù)幀的指針packet.size = 0;//這個填入H264數(shù)據(jù)幀的大小FILE *myH264 = fopen("1.264", "rb");//解碼的文件264if(myH264 == NULL){perror("cant open 264 file\n");return -1;}FILE *yuvfile = fopen("my264.yuv", "wb");//成功解碼后保存成的YUV文件, 能夠用YUV工具打開瀏覽if(yuvfile == NULL){perror("cant open YUV file\n");return -1;}int readFileLen = 1;char readBuf[MAX_LEN];unsigned char *parseBuf = malloc(20*MAX_LEN);//這個地方浪費了我一個下午時間, 當時我用的是棧內(nèi)存。即unsigned char parseBuf[20*MAX_LEN]。 結(jié)果執(zhí)行程序一直報錯, 此處須要用堆內(nèi)存才干正常解碼int parseBufLen = 0;int frameCount = 0;printf("begin...\n");printf("readBuf address is %x\n", readBuf); /SDL initSDL_Surface* hello = NULL;SDL_Surface* screen = NULL;//Start SDL// SDL_Init( SDL_INIT_EVERYTHING );SDL_Init(SDL_INIT_VIDEO);//Set up screenscreen = SDL_SetVideoMode( 1024, 768, 32, SDL_SWSURFACE );SDL_Overlay* overlay = SDL_CreateYUVOverlay(w, h, SDL_YV12_OVERLAY, screen);SDL_LockSurface(screen);SDL_LockYUVOverlay(overlay); //while(readFileLen > 0)//開始解碼工作{//printf("begin...\n");readFileLen = fread(readBuf, 1, sizeof(readBuf), myH264);//首先從文件中讀出數(shù)據(jù)if(readFileLen <= 0){printf("read over\n");break;}else{int handleLen = 0;int handleFileLen = readFileLen;while(handleFileLen > 0){int nLength = av_parser_parse2(avParserContext, codec_, &parseBuf, &parseBufLen, readBuf + handleLen, handleFileLen, 0, 0, 0);//查找264幀頭handleFileLen -= nLength;handleLen += nLength;if(parseBufLen <= 0)//當parseBufLen大于0時,說明查找到了幀頭{continue;}packet.size = parseBufLen;//將查找到的幀長度送入packet.data = parseBuf;//將查找到的幀內(nèi)存送入if(frameCount>100)break;//printf("parseBuf address is %x\n", parseBuf);while(packet.size > 0){//以下開始真正的解碼int decodeLen = avcodec_decode_video2(codec_, pFrame_, &frameFinished, &packet);if(decodeLen < 0)break;packet.size -= decodeLen;packet.data += decodeLen;if(frameFinished > 0)//成功解碼{int picSize = codec_->height * codec_->width;//int newSize = picSize * 1.5;//申請內(nèi)存//unsigned char *buf = malloc(newSize);int height = pFrame_->height;int width = pFrame_->width;//printf("OK, get data\n");//printf("Frame height is %d\n", height);//printf("Frame width is %d\n", width);frameCount ++;printf("Frame count is %d\n", frameCount);pgm_save(pFrame_->data[0], pFrame_->linesize[0],//保存Ycodec_->width, codec_->height, yuvfile);pgm_save(pFrame_->data[1], pFrame_->linesize[1],//保存Ucodec_->width/2, codec_->height/2, yuvfile);pgm_save(pFrame_->data[2], pFrame_->linesize[2],//保存Vcodec_->width/2, codec_->height/2, yuvfile);///有了YUV數(shù)據(jù)。 后面能夠用FFMPEG提供的轉(zhuǎn)換方法。將其轉(zhuǎn)成RGB數(shù)據(jù),進行興許的顯示或其他的圖像處理工作sdlint i;for(i=0;i<576;i++){//fwrite(buf + i * wrap, 1, xsize, f);memcpy(overlay->pixels[0]+i*720, pFrame_->data[0]+i*pFrame_->linesize[0], 720); }for(i=0;i<288;i++){memcpy(overlay->pixels[2]+i*360, pFrame_->data[1]+i*pFrame_->linesize[1], 360);memcpy(overlay->pixels[1]+i*360, pFrame_->data[2]+i*pFrame_->linesize[2], 360); }SDL_UnlockYUVOverlay(overlay);SDL_UnlockSurface(screen);rect.w = w;rect.h = h;rect.x = rect.y = 0;SDL_DisplayYUVOverlay(overlay, &rect);//sdl//SDL_Delay(40);}elseprintf("failed to decodec\n");}}}}//釋放工作avcodec_close(codec_);av_free(codec_);av_free_packet(&packet);av_frame_free(&pFrame_);//SDLSDL_FreeYUVOverlay(overlay);SDL_FreeSurface(screen);//Quit SDLSDL_Quit();fclose(yuvfile);fclose(myH264);}


總結(jié)

以上是生活随笔為你收集整理的嵌入式linux------ffmpeg移植 解码H264(am335x解码H264到yuv420并通过SDL显示)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。