嵌入式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 ...
随机推荐
- 基于Java的Arc Engine二次开发的环境的配置
1.软件准备 ArcGIS for Desktop 10.2, Arc engine, jdk-7u60-windows-i586,Eclipse Mar2 2.软件的安装 2.1 ArcGIS fo ...
- gulp压缩文件最简示例
安装gulp-uglify 作为项目的开发依赖即可 $ npm gulp-uglify --save-dev 压缩js文件 gulpfile.js const gulp = require('gulp ...
- Spring源码情操陶冶-PathMatchingResourcePatternResolver路径资源匹配溶解器
本文简单的分析下spring对某个目录下的class资源是如何做到全部的加载 PathMatchingResourcePatternResolver#getResources PathMatching ...
- 济南清北学堂游记 Day 6.
还剩一天半我就该回去了. 说实话今天挺可惜的,有很多本来可以得到的分数评测时没有拿到.上午的第一题和第二题我都想出了正解,T3敲了一个暴力,虽然暴力写坏了.预计是可以拿210的但是实际上只有很少的分数 ...
- 2018/2/14 设计模式学习笔记(一) 自己实现ArrayList,LinkedList和Iterator,以及在此过程中对于面向对象,面向接口,还有抽象类的一些思考感悟
因为本人目前为止学习编程不过七个月,所以后面的感悟对于一些大神来说可能嗤之以鼻,但对于一些刚刚入门的萌新来说在理解面向对象的思想上,以及抽象类和接口应该怎么设计等方面应该还是会有所帮助的 首先我们定义 ...
- Hibernate之HelloWorld
1. 步骤 0. 导入相关Jar包. 1. 编写Hibernate的持久化文件 (默认为hibernate.cfg.xml). 2. 编写持久化类. 3. 创建对象 - 关系文件(.htm.xml文件 ...
- txt文本文件记录日志
private static void Log(string content, string fileName="log.txt") { string logsPath = App ...
- 使用tcp+select实现客户端与客户端的通信
使用多路复用实现客户端与客户端进行通信: 原理:客户端只要一连上服务器,立马给服务器发送用户名,然后在服务端将newsocketfd存放在同一个结构体中,客户端先给服务器发送数据,然后通过服务器转发给 ...
- CSS常用属性计算原理
absolute: left.right/top.bottom 的百分比值分别根据父元素的 wdith / height 计算 margin: top /right / bottom/ left 的百 ...
- python学习:猜数字游戏
猜数字游戏 系统生成一个100以内的随机整数, 玩家有6次机会进行猜猜看,每次猜测都有反馈(猜大了,猜小了,猜对了-结束) 6次中,猜对了,玩家赢了. 否则系统赢了 #!/usr/bin/en ...