嵌入式linux------ffmpeg移植 解码H264(am335x解码H264到yuv420并通过SDL显示)
/* 编译命令: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 ////此方法参考官网的例子 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; } //初始化参数,下面的参数应该由具体的业务决定 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 成功打开解码器后, 此时可以分配帧内存, 当然你也可以在后面每次都分配、释放, 在此我省功夫, 只在开始分配一次 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;//这个是随便填入数字,没什么作用 av_init_packet(&packet); packet.data = NULL;//这里填入一个指向完整H264数据帧的指针 packet.size = 0;//这个填入H264数据帧的大小 FILE *myH264 = fopen("1.264", "rb");//解码的文件264 if(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);//这个地方浪费了我一个下午时间, 当时我用的是栈内存,即unsigned char parseBuf[20*MAX_LEN], 结果运行程序一直报错, 此处需要用堆内存才能正常解码 int parseBufLen = 0; int frameCount = 0; printf("begin...\n"); printf("readBuf address is %x\n", readBuf); /////////////////////////SDL init//////////////////////////////////////// SDL_Surface* hello = NULL; SDL_Surface* screen = NULL; //Start SDL // SDL_Init( SDL_INIT_EVERYTHING ); SDL_Init(SDL_INIT_VIDEO); //Set up screen screen = 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);//首先从文件里读出数据 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;//将查找到的帧内存送入 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; //申请内存 //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],//保存Y codec_->width, codec_->height, yuvfile); pgm_save(pFrame_->data[1], pFrame_->linesize[1],//保存U codec_->width/2, codec_->height/2, yuvfile); pgm_save(pFrame_->data[2], pFrame_->linesize[2],//保存V codec_->width/2, codec_->height/2, yuvfile); ///有了YUV数据, 后面可以用FFMPEG提供的转换方法,将其转成RGB数据,进行后续的显示或其它的图像处理工作 ////sdl int 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); } else printf("failed to decodec\n"); } } } } //////释放工作 avcodec_close(codec_); av_free(codec_); av_free_packet(&packet); av_frame_free(&pFrame_); //SDL SDL_FreeYUVOverlay(overlay); SDL_FreeSurface(screen); //Quit SDL SDL_Quit(); fclose(yuvfile); fclose(myH264); }
嵌入式linux------ffmpeg移植 解码H264(am335x解码H264到yuv420并通过SDL显示)的更多相关文章
- 【课程分享】深入浅出嵌入式linux系统移植开发 (环境搭建、uboot的移植、嵌入式内核的配置与编译)
深入浅出嵌入式linux系统移植开发 (环境搭建.uboot的移植.嵌入式内核的配置与编译) 亲爱的网友,我这里有套课程想和大家分享,假设对这个课程有兴趣的,能够加我的QQ2059055336和我联系 ...
- 嵌入式linux系统移植(一)
内容: 交叉编译环境 bootloader功能子系统 内核核心子系统 文件系统子系统要点: 搭建交叉编译环境 bootloader的选择和移植 kernel的配置.编译.移植和调 ...
- 嵌入式Linux系统移植——uboot常用命令
flash的一般分区: 其它数据 环境变量 可执行程序.如bootloader print(可缩写为:pri):打印查看uboot这个软件中集成的环境变量setenv.saveenv:设置.保存环境变 ...
- 嵌入式Linux系统移植(二)——交叉编译工具集
常用工具:readelf.size.nm.strip.strings.objdump.objcopy.addr2line readelf:读可执行文件的elf头 ELF Header: Magic: ...
- 手把手带你基于嵌入式Linux移植samba服务
摘要:Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件,由服务器及客户端程序构成. 本文分享自华为云社区<嵌入式Linux下移植samba服务--<基于北斗和4G ca ...
- 嵌入式linux和嵌入式android系统有什么区别和联系?
转自:http://bbs.eeworld.com.cn/thread-430437-1-1.html 这个问题很多人问,尤其是初入嵌入式的菜鸟.其实大家都认为android是java,已经不是lin ...
- [ffmpeg] h264并行解码
ffmpeg中的并行解码分为两种: Frame-level Parallelism Slice-level Parallelism Frame-level Parallelism 帧间依赖 我们之前讨 ...
- ffmpeg H264 编解码配置
ffmpeg H264编解码前面有文章介绍下,本文主要介绍一些参数配置. 编码: int InitEncoderCodec( int iWidth, int iHeight) { AVCodec * ...
- 利用ffmpeg将H264流 解码为RGB
利用H264解码分为几个步骤: 注意一点在添加头文件的时候要添加extern "C",不然会出现错误 [cpp] view plaincopy extern "C&quo ...
随机推荐
- 在线生成PDF的网站-HTML 转 PDF 在线
http://pdf.df5d.com/ (服务器问题,演示暂停了,但是 下面介绍的组件还是可以使用的) 将前面用到的wkhtmltopdf用一个服务器程序集成在一起,接受一个URL参数,在生成一 ...
- [DeeplearningAI笔记]Batch NormalizationBN算法Batch归一化_02_3.4-3.7
Batch Normalization Batch归一化 觉得有用的话,欢迎一起讨论相互学习~Follow Me 3.4正则化网络的激活函数 Batch归一化会使你的参数搜索问题变得很容易,使神经网络 ...
- 包装类和基本类型区别?(integer和int取值范围一样大)
1.声明方式不同,int不需要new .Integer需要new 2.性质上根本不同点:int是基本数据类型.Integer是引用数据类型,它有自己的属性,方法 3.存储位置和方式不同:int是存储在 ...
- 针对Chrome谷歌等浏览器不再支持showModalDialog的解决方案
最近在维护一个老项目,之前都是用IE来调试代码的.今天想着测试一下项目的兼容性,就用了谷歌浏览器,然后就遇到这样一个问题:一段用showModalDialog实现弹出模态框和返回值的js代码,在调试时 ...
- Spring Boot-JPA
前文我们使用SPRING INITIALIZR快速构建了一个空的Spring Boot项目,并增加web模块实现了HTTP请求. 这一篇继续在该demo的基础上,增加JPA的功能. JPA全称Java ...
- C# Ioc ASP.NET MVC Dependency Injection
ASP.NET MVC Dependency Injection 同志们,非常快速的Ioc注册接口和注入Mvc Controller,步骤如下: 安装Unity.Mvc NuGet Package 在 ...
- vue项目实现记住密码到cookie功能(附源码)
实现功能: 1.记住密码勾选,点登陆时,将账号和密码保存到cookie,下次登陆自动显示到表单内 2.不勾选,点登陆时候则清空之前保存到cookie的值,下次登陆需要手动输入 大体思路就是通过存/取/ ...
- springboot(二十):使用spring-boot-admin对spring-boot服务进行监控
上一篇文章<springboot(十九):使用Spring Boot Actuator监控应用>介绍了Spring Boot Actuator的使用,Spring Boot Actuato ...
- getHibernateTemplate() VS getSession()
如题所示,对于这个问题,官网文档已给出答案,详见: /** * Obtain a Hibernate Session, either from the current transaction or * ...
- SDP(5):ScalikeJDBC- JDBC-Engine:Streaming
作为一种通用的数据库编程引擎,用Streaming来应对海量数据的处理是必备功能.同样,我们还是通过一种Context传递产生流的要求.因为StreamingContext比较简单,而且还涉及到数据抽 ...