linux之x86裁剪移植---ffmpeg的H264解码显示(420、422)
在虚拟机上yuv420可以正常显示 ,而945(D525)模块上却无法显示 ,后来验证了directdraw的yuv420也无法显示 ,由此怀疑显卡不支持 ,后把420转换为422显示。
420显示如下:
/* 编译命令: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 gcc -o test test.c -I/usr/local/ffmpeg/include/ -L/usr/local/ffmpeg/lib/ -lswresample -lavformat -lavutil -lavcodec -lswscale -lx264 -lSDL */ #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 "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(AV_CODEC_ID_H264);//得到264的解码器类 if(!videoCodec) { printf("avcodec_find_decoder error\n"); return -1; } AVCodecParserContext *avParserContext = av_parser_init(AV_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_ = av_frame_alloc();// 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*1280, pFrame_->data[0]+i*pFrame_->linesize[0], 720); } for(i=0;i<288;i++) { memcpy(overlay->pixels[2]+i*640, pFrame_->data[1]+i*pFrame_->linesize[1], 360); memcpy(overlay->pixels[1]+i*640, 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); }
422显示如下:
/* 编译命令: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 gcc -o test test.c -I/usr/local/ffmpeg/include/ -L/usr/local/ffmpeg/lib/ -lswresample -lavformat -lavutil -lavcodec -lswscale -lx264 -lSDL */ #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 "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(AV_CODEC_ID_H264);//得到264的解码器类 if(!videoCodec) { printf("avcodec_find_decoder error\n"); return -1; } AVCodecParserContext *avParserContext = av_parser_init(AV_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_ = av_frame_alloc();// 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( 720, 576, 32, SDL_SWSURFACE ); SDL_Overlay* overlay = SDL_CreateYUVOverlay(w, h, SDL_YUY2_OVERLAY, screen); SDL_LockSurface(screen); SDL_LockYUVOverlay(overlay); unsigned char yuv422[768*576*2]; ////////////////////////////////////////////////////////////////////// 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); }*/ int k=0,y,x; //yuv420 -> yuv422 for( y=0;y<576;y++) { for( x=0;x<720;x++) { yuv422[k++] = pFrame_->data[0][y*pFrame_->linesize[0]+x]; yuv422[k++] = x%2==0?pFrame_->data[1][(y/2)*pFrame_->linesize[1]+x/2]:pFrame_->data[2][(y/2)*pFrame_->linesize[2]+x/2]; } } memcpy(overlay->pixels[0],yuv422, codec_->width*codec_->height*2); 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); }
采用sws_scale 实现的数据转换
/* 编译命令: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 gcc -o test test.c -I/usr/local/ffmpeg/include/ -L/usr/local/ffmpeg/lib/ -lswresample -lavformat -lavutil -lavcodec -lswscale -lx264 -lSDL */ #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 "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,*pFrameYUV; struct SwsContext *img_convert_ctx =NULL; pFrameYUV =av_frame_alloc(); /* find the video encoder */ AVCodec *videoCodec = avcodec_find_decoder(AV_CODEC_ID_H264);//得到264的解码器类 if(!videoCodec) { printf("avcodec_find_decoder error\n"); return -1; } AVCodecParserContext *avParserContext = av_parser_init(AV_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_ = av_frame_alloc();// 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( 720, 576, 32, SDL_SWSURFACE ); SDL_Overlay* overlay = SDL_CreateYUVOverlay(w, h, SDL_YUY2_OVERLAY, screen); SDL_LockSurface(screen); SDL_LockYUVOverlay(overlay); ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// int numBytes = avpicture_get_size(AV_PIX_FMT_YUYV422, codec_->width, codec_->height); uint8_t* yuv422 = (uint8_t *)av_malloc(numBytes*sizeof(uint8_t)); avpicture_fill((AVPicture *)pFrameYUV, yuv422, AV_PIX_FMT_YUYV422, codec_->width, codec_->height); /////////////////////////////////////////////////////////////////////// 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); }*/ img_convert_ctx = sws_getContext(codec_->width, codec_->height, codec_->pix_fmt, codec_->width, codec_->height, AV_PIX_FMT_YUYV422, 2, NULL, NULL, NULL); sws_scale(img_convert_ctx, (const uint8_t* const*) pFrame_->data, pFrame_->linesize, 0, codec_->height, pFrameYUV->data,pFrameYUV->linesize); memcpy(overlay->pixels[0],yuv422, codec_->width*codec_->height*2); 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之x86裁剪移植---ffmpeg的H264解码显示(420、422)的更多相关文章
- linux之x86裁剪移植---grub 识别文件系统
grub主要作用是找到内核(kernel)与部分核心模块的镜像(initrd,主要是sata硬盘驱动之类的模块),把它们导入内存中运行.kernel与initrd放在文件系统中,因此grub必须有识别 ...
- linux之x86裁剪移植---字符界面sdl开发入门
linux下有没有TurboC2.0那样的画点.线.圆的图形函数库,有没有grapihcs.h,或者与之相对应或相似的函数库是什么?有没有DirectX这样的游戏开发库?SDL就是其中之一. SDL( ...
- 利用ffmpeg将H264解码为RGB
因为公司买到了一个不提供解码器的设备,我不得已还要做解码的工作.在网上找了一圈,H264解码比較方便的也就是ffmpeg一系列的函数库了,原本设备中也是用这套函数库解码,但厂家不给提供,没办法,仅仅得 ...
- 移植ffmpeg到VC环境心得
所有想学习ffmpeg的网友有福了,大名鼎鼎的ffmpeg,移植到Windows的VC6版本全部开源,编译环境为VC6+SP5+VCPP5.别忘记了顶贴哦. 移植ffmpeg到windows,主要的修 ...
- [Linux][Madplay播放器移植mini2440(ARM9)]
Madplay移植到mini2440全过程详解 madplay交叉编译 交叉编译器:arm-linux-gcc 3.4.1PC环境:RedHat-6 注意:最好在root权限下执行以下移植,否则在ma ...
- Arm-Linux 移植 FFMPEG库 + x264
背景: ffmpeg 中带有264的解码,没有编码,需要添加x264.libx264是一个自由的H.264编码库,是x264项目的一部分,使用广泛,ffmpeg的H.264实现就是用的libx26 ...
- 【FFMPEG】【ARM-Linux开发】fmpeg安装第三方编码器(encoder)库,ffmpeg编码h264(完)
fmpeg安装第三方编码器(encoder)库,ffmpeg编码h264(完) ffmpeg安装第三方编码器(encoder)库 关键词:ffmpeg.编码h264.第三方encoder 安装好了ff ...
- Ubuntu 移植 ffmpeg + x264
背景 直接编译移植的ffmpeg是与 arm-linux 下类似的. 详情参考: arm linux 移植 FFMPEG库 + x264 host平台 :Ubuntu 16.04 x264 :2017 ...
- XAMPP(Linux版-x86兼容)官网下载
欢迎光临 XAMPP 的 Linux 版 (x86 兼容处理器版)顺便提一下:该软件以前被称作 LAMPP,但为了避免误解,我们将其重名命为 »XAMPP 的 Linux 版«.所以,如果您在寻找 L ...
随机推荐
- c# 可变字符串 StringBuilder
普通的string不可变,除非用+ 但是+两个字符串后 会生成一个新的string实例.会在内存中创建新的字符串对象.如果重复的对字符串修改,将极大的增加内存开销.c#提供了个可变的字符串序列Stri ...
- 【AIX】AIX内存机制
[AIX]AIX内存机制 1 虚拟内存 虚拟内存是物理内存和交换空间(Paging Space)组合形成的虚拟内存空间, 通过虚拟的地址空间映射到物理内存或者 Paging Space. 在 AIX ...
- Windows实用命令
Windows实用命令 # 统计ESTABLISHED状态下的连接一共有多少个/c是统计行数,/i是忽略大小写 netstat -ano|find /i "established&qu ...
- Java多线程基础(二)
信号量Semaphore,类似于锁的功能,用于多线程中对一组资源的控制. acquire方法用于尝试获取一个资源,未获取前将一直等待.release用于释放一个资源,release的前提是已经获得了一 ...
- MOBA战斗服务器设计思路
MOBA作为竞技类的游戏,游戏中实时高精度同步,或者又说延迟容错率的要求还算是比较高的一种. 如何做到这种同步机制呢? 常用的同步机制有两种类型:帧同步 / 指令同步 何谓帧同步? 保证双方客户端逻辑 ...
- 2017人生总结(MECE分析法)
试着用MECE分析法对人生的整个规划做一下总结.作为技术人员,其实除了编码架构能力之外,分析问题的能力的重要程度也会随着职业发展越来越重要.<美团点评技术博客>说这几天要在黄金时段头版头条 ...
- xBIM WeXplorer xViewer 基本应用
目录 基础 xBIM WeXplorer 简要介绍 xBIM WeXplorer xViewer 基本应用 xBIM WeXplorer xViewer 浏览器检查 xBIM WeXplorer xV ...
- Ubuntu下的Samba服务器配置
一. samba的安装: sudo apt-get insall samba 二. 创建共享目录: mkdir /home/phinecos/share sodu chmod 777 /home/ge ...
- ionic2+Angular 组件(多个组件)浅谈
第一步,新建组件: ionic g component product-img-list 命令执行成功之后项目中生成的文件: 第二步:生成文件解析: ①product-img-list.ts impo ...
- 利用UICollectionView实现列表和宫格视图的切换
很多时候我们需要列表和宫格视图的来回切换,就像苹果的天气应用一样,我之前见过一个用tableview和collectionview来实现这种效果的,我本人不太喜欢这个,那么有没有更好的方法呢?答案是: ...