FFMPEG:H264解码-SDL显示(RGB32、RGB24、YUV420P、YUV422)
1. 注册所有容器格式: av_register_all()
2. 打开文件: av_open_input_file()
3. 从文件中提取流信息: av_find_stream_info()
4. 穷举所有的流,查找其中种类为CODEC_TYPE_VIDEO
5. 查找对应的解码器: avcodec_find_decoder()
6. 打开编解码器: avcodec_open()
7. 为解码帧分配内存: avcodec_alloc_frame()
8. 不停地从码流中提取出帧数据: av_read_frame()
9. 判断帧的类型,对于视频帧调用: avcodec_decode_video()
10. 解码完后,释放解码器: avcodec_close()
11. 关闭输入文件:av_close_input_file()
//添加的库:avcodec.lib avdevice.lib avfilter.lib avformat.lib avutil.lib swscale.lib SDL.lib
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libsdl/SDL.h>
#include <libsdl/SDL_thread.h>
};
void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame)
{
FILE *pFile;
char szFilename[32];
int y;
// Open file
sprintf(szFilename, "frame%d.ppm", iFrame);
pFile=fopen(szFilename, "wb");
if(pFile==NULL)
return;
// Write header
fprintf(pFile, "P6\n%d %d\n255\n", width, height);
// Write pixel data
for(y=0; y<height; y++)
fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);
// Close file
fclose(pFile);
}
void CTest0Dlg::OnButton1()
{
// TODO: Add your control notification handler code here
AVFormatContext *pFormatCtx;
int i, videoStream;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame;
AVFrame *pFrameRGB;
AVPacket packet;
int frameFinished;
int numBytes;
uint8_t *buffer;
static int sws_flags = SWS_BICUBIC;
struct SwsContext *img_convert_ctx;
AVPicture pict;
// argc = 2;
char argv[100] = "d:\\temp\\VIDEO720576.264";
// argv[1] = "d:\\temp\\ff.mpg";
// /*注册所有可用的格式和编解码器*/
av_register_all();
// Open video file /*以输入方式打开一个媒体文件,也即源文件,codecs并没有打开,只读取了文件的头信息*/
if(av_open_input_file(&pFormatCtx, argv, NULL, 0, NULL)!=0)
return ; // Couldn't open file
// Retrieve stream information
/*通过读取媒体文件的中的包来获取媒体文件中的流信息,对于没有头信息的文件如(mpeg)是非常有用的,
// 该函数通常重算类似mpeg-2帧模式的真实帧率,该函数并未改变逻辑文件的position.
*/
if(av_find_stream_info(pFormatCtx)<0)
return ; // Couldn't find stream information
// Dump information about file onto standard error
//该函数的作用就是检查下初始化过程中设置的参数是否符合规范
dump_format(pFormatCtx, 0, argv, 0);
// Find the first video stream
videoStream=-1;
printf("%d\n",pFormatCtx->nb_streams);
getchar();
for(i=0; i<pFormatCtx->nb_streams; i++)
if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO&&videoStream < 0)
{
videoStream=i;
break;
}
if(videoStream==-1)
return ; // Didn't find a video stream
// Get a pointer to the codec context for the video stream
pCodecCtx=pFormatCtx->streams[videoStream]->codec;
// Find the decoder for the video stream
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
/*通过code ID查找一个已经注册的音视频编码器,查找编码器之前,必须先调用av_register_all注册所有支持的编码器
音视频编码器保存在一个链表中,查找过程中,函数从头到尾遍历链表,通过比较编码器的ID来查找
*/
if(pCodec==NULL) {
fprintf(stderr, "Unsupported codec!\n");
return ; // Codec not found
}
// Open codec
//使用给定的AVCodec初始化AVCodecContext
if(avcodec_open(pCodecCtx, pCodec)<0)
return ; // Could not open codec
//printf("name %s\n",pCodec->name);
//getchar();
// Allocate video frame
pFrame=avcodec_alloc_frame();
// Allocate an AVFrame structure
pFrameRGB=avcodec_alloc_frame();
if(pFrameRGB==NULL)
return ;
// Determine required buffer size and allocate buffer
numBytes=avpicture_get_size(PIX_FMT_RGB32, pCodecCtx->width,
pCodecCtx->height);
buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
// Assign appropriate parts of buffer to image planes in pFrameRGB
// Note that pFrameRGB is an AVFrame, but AVFrame is a superset
// of AVPicture
avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB32,
pCodecCtx->width, pCodecCtx->height);
// Read frames and save first five frames to disk
i=0;
////////////////////////////////////////////////////////////////
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
fprintf(stderr, "can not initialize SDL:%s\n", SDL_GetError());
exit(1);
}
atexit(SDL_Quit);
SDL_Surface *screen;
screen = SDL_SetVideoMode(720, 576, 32, SDL_SWSURFACE|SDL_ANYFORMAT);
if ( screen == NULL )
{
exit(2);
}
SDL_Surface *image;
Uint32 rmask, gmask, bmask, amask;
/* SDL interprets each pixel as a 32-bit number, so our masks must depend
on the endianness (byte order) of the machine */
#if 0//SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
#else
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
#endif
image = SDL_CreateRGBSurface(SDL_SWSURFACE, 720, 576, 0,
rmask, gmask, bmask, NULL);
if(image == NULL)
{
//fprintf(stderr, "CreateRGBSurface failed: %s\n", SDL_GetError());
exit(1);
}
//////////////////////////////////////////////////////////////////
while(av_read_frame(pFormatCtx, &packet)>=0)
{
// Is this a packet from the video stream?
if(packet.stream_index==videoStream)
{
// Decode video frame
avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,
packet.data, packet.size);
// Did we get a video frame?
if(frameFinished)
{
// Convert the image from its native format to RGB
img_convert_ctx = sws_getContext( pCodecCtx->width,
pCodecCtx->height,
pCodecCtx->pix_fmt,
pCodecCtx->width,
pCodecCtx->height,
PIX_FMT_RGB32,
sws_flags, NULL, NULL, NULL);
sws_scale(img_convert_ctx,pFrame->data,pFrame->linesize,0,pCodecCtx->height,pFrameRGB->data,pFrameRGB->linesize);
sws_freeContext(img_convert_ctx);
////////////////////////////////////////////////////////////////
memcpy(screen->pixels,buffer,720*576*4);
SDL_UpdateRect(screen, 0, 0, image->w, image->h);
/* Free the allocated BMP surface */
SDL_FreeSurface(image);
/////////////////////////////////////////////////////////////////
// Save the frame to disk
if((++i<=5))
SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i);
}
}
// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
}
// Free the RGB image
av_free(buffer);
av_free(pFrameRGB);
// Free the YUV frame
av_free(pFrame);
// Close the codec
avcodec_close(pCodecCtx);
// Close the video file
av_close_input_file(pFormatCtx);
MessageBox("over");
}
void CTest0Dlg::OnButton2()
{
// TODO: Add your control notification handler code here
AVFormatContext *pFormatCtx;
int i, videoStream;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame;
AVFrame *pFrameRGB;
AVPacket packet;
int frameFinished;
int numBytes;
uint8_t *buffer;
static int sws_flags = SWS_BICUBIC;
struct SwsContext *img_convert_ctx;
AVPicture pict;
// argc = 2;
char argv[100] = "d:\\temp\\VIDEO720576.264";
// argv[1] = "d:\\temp\\ff.mpg";
// /*注册所有可用的格式和编解码器*/
av_register_all();
// Open video file /*以输入方式打开一个媒体文件,也即源文件,codecs并没有打开,只读取了文件的头信息*/
if(av_open_input_file(&pFormatCtx, argv, NULL, 0, NULL)!=0)
return ; // Couldn't open file
// Retrieve stream information
/*通过读取媒体文件的中的包来获取媒体文件中的流信息,对于没有头信息的文件如(mpeg)是非常有用的,
// 该函数通常重算类似mpeg-2帧模式的真实帧率,该函数并未改变逻辑文件的position.
*/
if(av_find_stream_info(pFormatCtx)<0)
return ; // Couldn't find stream information
// Dump information about file onto standard error
//该函数的作用就是检查下初始化过程中设置的参数是否符合规范
dump_format(pFormatCtx, 0, argv, 0);
// Find the first video stream
videoStream=-1;
printf("%d\n",pFormatCtx->nb_streams);
getchar();
for(i=0; i<pFormatCtx->nb_streams; i++)
if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO&&videoStream < 0)
{
videoStream=i;
break;
}
if(videoStream==-1)
return ; // Didn't find a video stream
// Get a pointer to the codec context for the video stream
pCodecCtx=pFormatCtx->streams[videoStream]->codec;
// Find the decoder for the video stream
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
/*通过code ID查找一个已经注册的音视频编码器,查找编码器之前,必须先调用av_register_all注册所有支持的编码器
音视频编码器保存在一个链表中,查找过程中,函数从头到尾遍历链表,通过比较编码器的ID来查找
*/
if(pCodec==NULL) {
fprintf(stderr, "Unsupported codec!\n");
return ; // Codec not found
}
// Open codec
//使用给定的AVCodec初始化AVCodecContext
if(avcodec_open(pCodecCtx, pCodec)<0)
return ; // Could not open codec
//printf("name %s\n",pCodec->name);
//getchar();
// Allocate video frame
pFrame=avcodec_alloc_frame();
// Allocate an AVFrame structure
pFrameRGB=avcodec_alloc_frame();
if(pFrameRGB==NULL)
return ;
// Determine required buffer size and allocate buffer
numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,
pCodecCtx->height);
buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
// Assign appropriate parts of buffer to image planes in pFrameRGB
// Note that pFrameRGB is an AVFrame, but AVFrame is a superset
// of AVPicture
avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
pCodecCtx->width, pCodecCtx->height);
// Read frames and save first five frames to disk
i=0;
////////////////////////////////////////////////////////////////
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
fprintf(stderr, "can not initialize SDL:%s\n", SDL_GetError());
exit(1);
}
atexit(SDL_Quit);
SDL_Surface *screen;
screen = SDL_SetVideoMode(720, 576, 24, SDL_SWSURFACE|SDL_ANYFORMAT);
if ( screen == NULL )
{
exit(2);
}
SDL_Surface *image;
Uint32 rmask, gmask, bmask, amask;
/* SDL interprets each pixel as a 32-bit number, so our masks must depend
on the endianness (byte order) of the machine */
#if 0//SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
#else
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
#endif
image = SDL_CreateRGBSurface(SDL_SWSURFACE, 720, 576, 0,
rmask, gmask, bmask, NULL);
if(image == NULL)
{
//fprintf(stderr, "CreateRGBSurface failed: %s\n", SDL_GetError());
exit(1);
}
//////////////////////////////////////////////////////////////////
while(av_read_frame(pFormatCtx, &packet)>=0)
{
// Is this a packet from the video stream?
if(packet.stream_index==videoStream)
{
// Decode video frame
avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,
packet.data, packet.size);
// Did we get a video frame?
if(frameFinished)
{
// Convert the image from its native format to RGB
img_convert_ctx = sws_getContext( pCodecCtx->width,
pCodecCtx->height,
pCodecCtx->pix_fmt,
pCodecCtx->width,
pCodecCtx->height,
PIX_FMT_BGR24,
sws_flags, NULL, NULL, NULL);
sws_scale(img_convert_ctx,pFrame->data,pFrame->linesize,0,pCodecCtx->height,pFrameRGB->data,pFrameRGB->linesize);
sws_freeContext(img_convert_ctx);
////////////////////////////////////////////////////////////////
memcpy(screen->pixels,buffer,720*576*3);
SDL_UpdateRect(screen, 0, 0, image->w, image->h);
/* Free the allocated BMP surface */
SDL_FreeSurface(image);
/////////////////////////////////////////////////////////////////
// Save the frame to disk
if((++i<=5))
SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i);
}
}
// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
}
// Free the RGB image
av_free(buffer);
av_free(pFrameRGB);
// Free the YUV frame
av_free(pFrame);
// Close the codec
avcodec_close(pCodecCtx);
// Close the video file
av_close_input_file(pFormatCtx);
MessageBox("over");
}
void CTest0Dlg::OnButton3()
{
// TODO: Add your control notification handler code here
// TODO: Add your control notification handler code here
AVFormatContext *pFormatCtx;
int i, videoStream;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame;
AVFrame *pFrameYUV;
AVPacket packet;
int frameFinished;
int numBytes;
uint8_t *buffer;
SDL_Rect rect;
static int sws_flags = SWS_BICUBIC;
struct SwsContext *img_convert_ctx;
AVPicture pict;
// argc = 2;
char argv[100] = "d:\\temp\\VIDEO720576.264";
// argv[1] = "d:\\temp\\ff.mpg";
// /*注册所有可用的格式和编解码器*/
av_register_all();
// Open video file /*以输入方式打开一个媒体文件,也即源文件,codecs并没有打开,只读取了文件的头信息*/
if(av_open_input_file(&pFormatCtx, argv, NULL, 0, NULL)!=0)
return ; // Couldn't open file
// Retrieve stream information
/*通过读取媒体文件的中的包来获取媒体文件中的流信息,对于没有头信息的文件如(mpeg)是非常有用的,
// 该函数通常重算类似mpeg-2帧模式的真实帧率,该函数并未改变逻辑文件的position.
*/
if(av_find_stream_info(pFormatCtx)<0)
return ; // Couldn't find stream information
// Dump information about file onto standard error
//该函数的作用就是检查下初始化过程中设置的参数是否符合规范
dump_format(pFormatCtx, 0, argv, 0);
// Find the first video stream
videoStream=-1;
printf("%d\n",pFormatCtx->nb_streams);
getchar();
for(i=0; i<pFormatCtx->nb_streams; i++)
if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO&&videoStream < 0)
{
videoStream=i;
break;
}
if(videoStream==-1)
return ; // Didn't find a video stream
// Get a pointer to the codec context for the video stream
pCodecCtx=pFormatCtx->streams[videoStream]->codec;
// Find the decoder for the video stream
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
/*通过code ID查找一个已经注册的音视频编码器,查找编码器之前,必须先调用av_register_all注册所有支持的编码器
音视频编码器保存在一个链表中,查找过程中,函数从头到尾遍历链表,通过比较编码器的ID来查找
*/
if(pCodec==NULL) {
fprintf(stderr, "Unsupported codec!\n");
return ; // Codec not found
}
// Open codec
//使用给定的AVCodec初始化AVCodecContext
if(avcodec_open(pCodecCtx, pCodec)<0)
return ; // Could not open codec
//printf("name %s\n",pCodec->name);
//getchar();
// Allocate video frame
pFrame=avcodec_alloc_frame();
// Allocate an AVFrame structure
pFrameYUV=avcodec_alloc_frame();
if(pFrameYUV==NULL)
return ;
// Determine required buffer size and allocate buffer
numBytes=avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width,
pCodecCtx->height);
buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
// Assign appropriate parts of buffer to image planes in pFrameRGB
// Note that pFrameRGB is an AVFrame, but AVFrame is a superset
// of AVPicture
avpicture_fill((AVPicture *)pFrameYUV, buffer, PIX_FMT_YUV420P,
pCodecCtx->width, pCodecCtx->height);
// Read frames and save first five frames to disk
i=0;
////////////////////////////////////////////////////////////////
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
fprintf(stderr, "can not initialize SDL:%s\n", SDL_GetError());
exit(1);
}
atexit(SDL_Quit);
SDL_Surface *screen;
screen = SDL_SetVideoMode(720, 576, 24, SDL_SWSURFACE|SDL_ANYFORMAT);
if ( screen == NULL )
{
exit(2);
}
SDL_Overlay *image;
image = SDL_CreateYUVOverlay(pCodecCtx->width,
pCodecCtx->height,
SDL_YV12_OVERLAY,
screen);
if(image == NULL)
{
//fprintf(stderr, "CreateRGBSurface failed: %s\n", SDL_GetError());
exit(1);
}
//////////////////////////////////////////////////////////////////
while(av_read_frame(pFormatCtx, &packet)>=0)
{
// Is this a packet from the video stream?
if(packet.stream_index==videoStream)
{
// Decode video frame
avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,
packet.data, packet.size);
// Did we get a video frame?
if(frameFinished)
{
// Convert the image from its native format to RGB
SDL_LockYUVOverlay(image);
// pFrameYUV->data[0] = image->pixels[0];//预先改变指针数据区,不用copy
// pFrameYUV->data[1] = image->pixels[2];
// pFrameYUV->data[2] = image->pixels[1];
//
// pFrameYUV->linesize[0] = image->pitches[0];
// pFrameYUV->linesize[1] = image->pitches[2];
// pFrameYUV->linesize[2] = image->pitches[1];
img_convert_ctx = sws_getContext( pCodecCtx->width,
pCodecCtx->height,
pCodecCtx->pix_fmt,
pCodecCtx->width,
pCodecCtx->height,
PIX_FMT_YUV420P,
sws_flags, NULL, NULL, NULL);
sws_scale(img_convert_ctx,pFrame->data,pFrame->linesize,0,pCodecCtx->height,pFrameYUV->data,pFrameYUV->linesize);
sws_freeContext(img_convert_ctx);
memcpy(image->pixels[0], pFrameYUV->data[0],720*576);//拷贝数据yuv420,也可预先改变指针
memcpy(image->pixels[2], pFrameYUV->data[1],720*576/4);
memcpy(image->pixels[1], pFrameYUV->data[2],720*576/4);
SDL_UnlockYUVOverlay(image);
rect.x = 0;
rect.y = 0;
rect.w = pCodecCtx->width;
rect.h = pCodecCtx->height;
SDL_DisplayYUVOverlay(image, &rect);
}
}
// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
}
// Free the RGB image
av_free(buffer);
av_free(pFrameYUV);
// Free the YUV frame
av_free(pFrame);
// Close the codec
avcodec_close(pCodecCtx);
// Close the video file
av_close_input_file(pFormatCtx);
MessageBox("over");
}
void CTest0Dlg::OnButton4()
{
// TODO: Add your control notification handler code here
// TODO: Add your control notification handler code here
AVFormatContext *pFormatCtx;
int i, videoStream;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame;
AVFrame *pFrameYUV;
AVPacket packet;
int frameFinished;
int numBytes;
uint8_t *buffer;
SDL_Rect rect;
static int sws_flags = SWS_BICUBIC;
struct SwsContext *img_convert_ctx;
AVPicture pict;
// argc = 2;
char argv[100] = "d:\\temp\\VIDEO720576.264";
// argv[1] = "d:\\temp\\ff.mpg";
// /*注册所有可用的格式和编解码器*/
av_register_all();
// Open video file /*以输入方式打开一个媒体文件,也即源文件,codecs并没有打开,只读取了文件的头信息*/
if(av_open_input_file(&pFormatCtx, argv, NULL, 0, NULL)!=0)
return ; // Couldn't open file
// Retrieve stream information
/*通过读取媒体文件的中的包来获取媒体文件中的流信息,对于没有头信息的文件如(mpeg)是非常有用的,
// 该函数通常重算类似mpeg-2帧模式的真实帧率,该函数并未改变逻辑文件的position.
*/
if(av_find_stream_info(pFormatCtx)<0)
return ; // Couldn't find stream information
// Dump information about file onto standard error
//该函数的作用就是检查下初始化过程中设置的参数是否符合规范
dump_format(pFormatCtx, 0, argv, 0);
// Find the first video stream
videoStream=-1;
printf("%d\n",pFormatCtx->nb_streams);
getchar();
for(i=0; i<pFormatCtx->nb_streams; i++)
if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO&&videoStream < 0)
{
videoStream=i;
break;
}
if(videoStream==-1)
return ; // Didn't find a video stream
// Get a pointer to the codec context for the video stream
pCodecCtx=pFormatCtx->streams[videoStream]->codec;
// Find the decoder for the video stream
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
/*通过code ID查找一个已经注册的音视频编码器,查找编码器之前,必须先调用av_register_all注册所有支持的编码器
音视频编码器保存在一个链表中,查找过程中,函数从头到尾遍历链表,通过比较编码器的ID来查找
*/
if(pCodec==NULL) {
fprintf(stderr, "Unsupported codec!\n");
return ; // Codec not found
}
// Open codec
//使用给定的AVCodec初始化AVCodecContext
if(avcodec_open(pCodecCtx, pCodec)<0)
return ; // Could not open codec
//printf("name %s\n",pCodec->name);
//getchar();
// Allocate video frame
pFrame=avcodec_alloc_frame();
// Allocate an AVFrame structure
pFrameYUV=avcodec_alloc_frame();
if(pFrameYUV==NULL)
return ;
// Determine required buffer size and allocate buffer
numBytes=avpicture_get_size(PIX_FMT_YUV422, pCodecCtx->width,
pCodecCtx->height);
buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
// Assign appropriate parts of buffer to image planes in pFrameRGB
// Note that pFrameRGB is an AVFrame, but AVFrame is a superset
// of AVPicture
avpicture_fill((AVPicture *)pFrameYUV, buffer, PIX_FMT_YUV422,
pCodecCtx->width, pCodecCtx->height);
// Read frames and save first five frames to disk
i=0;
////////////////////////////////////////////////////////////////
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
fprintf(stderr, "can not initialize SDL:%s\n", SDL_GetError());
exit(1);
}
atexit(SDL_Quit);
SDL_Surface *screen;
screen = SDL_SetVideoMode(720, 576, 24, SDL_SWSURFACE|SDL_ANYFORMAT);
if ( screen == NULL )
{
exit(2);
}
SDL_Overlay *image;
image = SDL_CreateYUVOverlay(pCodecCtx->width,
pCodecCtx->height,
SDL_YUY2_OVERLAY,
screen);
if(image == NULL)
{
//fprintf(stderr, "CreateRGBSurface failed: %s\n", SDL_GetError());
exit(1);
}
//////////////////////////////////////////////////////////////////
while(av_read_frame(pFormatCtx, &packet)>=0)
{
// Is this a packet from the video stream?
if(packet.stream_index==videoStream)
{
// Decode video frame
avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,
packet.data, packet.size);
// Did we get a video frame?
if(frameFinished)
{
// Convert the image from its native format to RGB
SDL_LockYUVOverlay(image);
// pFrameYUV->data[0] = image->pixels[0];
// pFrameYUV->data[1] = image->pixels[2];
// pFrameYUV->data[2] = image->pixels[1];
//
// pFrameYUV->linesize[0] = image->pitches[0];
// pFrameYUV->linesize[1] = image->pitches[2];
// pFrameYUV->linesize[2] = image->pitches[1];
img_convert_ctx = sws_getContext( pCodecCtx->width,
pCodecCtx->height,
pCodecCtx->pix_fmt,
pCodecCtx->width,
pCodecCtx->height,
PIX_FMT_YUV422,
sws_flags, NULL, NULL, NULL);
sws_scale(img_convert_ctx,pFrame->data,pFrame->linesize,0,pCodecCtx->height,pFrameYUV->data,pFrameYUV->linesize);
sws_freeContext(img_convert_ctx);
memcpy(image->pixels[0], pFrameYUV->data[0],720*576*2);//拷贝数据yuv422
SDL_UnlockYUVOverlay(image);
rect.x = 0;
rect.y = 0;
rect.w = pCodecCtx->width;
rect.h = pCodecCtx->height;
SDL_DisplayYUVOverlay(image, &rect);
}
}
// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
}
// Free the RGB image
av_free(buffer);
av_free(pFrameYUV);
// Free the YUV frame
av_free(pFrame);
// Close the codec
avcodec_close(pCodecCtx);
// Close the video file
av_close_input_file(pFormatCtx);
MessageBox("over");
}
http://download.csdn.net/detail/mao0514/8202691
FFMPEG:H264解码-SDL显示(RGB32、RGB24、YUV420P、YUV422)的更多相关文章
- ffmpeg h264+ts +(sdl)显示方式
网友: 明月惊鹊(357161826) 2014-1-16 10:07:00ffmpeg + sdl一米阳光(740053660) 2014-1-16 10:08:29Simple DirectMed ...
- FFMpeg.H264解码win开发环境搭建
开发环境: vc6.0 + sp5 + vcpp5,注意vcpp5在vc6+sp6上会安装失败. 源码: ff_264_dec_vc,可用vc进行编译调试,但编译环境限定如上. 声明:该工程是ffmp ...
- linux之x86裁剪移植---ffmpeg的H264解码显示(420、422)
在虚拟机上yuv420可以正常显示 ,而945(D525)模块上却无法显示 ,后来验证了directdraw的yuv420也无法显示 ,由此怀疑显卡不支持 ,后把420转换为422显示. 420显示如 ...
- 嵌入式linux------ffmpeg移植 解码H264(am335x解码H264到yuv420并通过SDL显示)
/* 编译命令:arm-linux-gcc -o show2642 264showyuv2.c -I/usr/local/ffmpeg_arm/include/ -L/usr/local/ffmpeg ...
- H264-YUV通过RTP接收视频流ffmpeg解码SDL实时播放
写在前面的话 写一个简单的播放器,通过RTP接收视频流,进行实时播放.最初,使用ffplay或者vlc接收按照SDP协议文件可以播放视频,但是视频中断后重启,不能正确的解包,时常会出现如下的错误信息. ...
- 利用ffmpeg将H264解码为RGB
因为公司买到了一个不提供解码器的设备,我不得已还要做解码的工作.在网上找了一圈,H264解码比較方便的也就是ffmpeg一系列的函数库了,原本设备中也是用这套函数库解码,但厂家不给提供,没办法,仅仅得 ...
- SDL 显示解码后的yuv12数据
在上篇h264解码为yuv12后http://jhlong12345.blog.163.com/blog/static/1230631292015725115058709/ ,需要显示出来,使用sdl ...
- ffmpeg H264 编解码配置
ffmpeg H264编解码前面有文章介绍下,本文主要介绍一些参数配置. 编码: int InitEncoderCodec( int iWidth, int iHeight) { AVCodec * ...
- ffmpeg 编解码详细过程
ffmpeg编解码详细过程 bobbypollo 转:ffmpeg编解码详细过程 原文地址:ffmpeg编解码详细过程(转)作者:心在飞翔原文出处: http://www.360doc.com ...
随机推荐
- ABP示例程序-使用AngularJs,ASP.NET MVC,Web API和EntityFramework创建N层的单页面Web应用
本片文章翻译自ABP在CodeProject上的一个简单示例程序,网站上的程序是用ABP之前的版本创建的,模板创建界面及工程文档有所改变,本文基于最新的模板创建.通过这个简单的示例可以对ABP有个更深 ...
- BZOJ 3990: [SDOI2015]排序 [搜索]
3990: [SDOI2015]排序 题意:\(2^n\)的一个排列,给你n种操作,第i种把每\(2^{i-1}\)个数看成一段,交换任意两段.问是这个序列有序的操作方案数,两个操作序列不同,当且仅当 ...
- vue 使用Jade模板写html,stylus写css
vue 使用Jade模板写html,stylus写css 日常工作都是使用vue开发页面和webApp,写的多了就想偷懒简化各种书写方式,所以使用了jade写html,stylus写css,省了很多的 ...
- yii2 源码分析 model类分析 (五)
模型类是数据模型的基类.此类继承了组件类,实现了3个接口 先介绍一下模型类前面的大量注释说了什么: * 模型类是数据模型的基类.此类继承了组件类,实现了3个接口 * 实现了IteratorAggreg ...
- Project support for both iOS 6 and iOS 7
原文:https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TransitionGuide/S ...
- Lua内存分析工具
最近给公司写了一个lua内存分析工具,可以非常方便的分析出Lua内存泄露问题,有图形化界面操作,方便手机端上传快照等功能 内存分析我是在c语言端写的,也有人写过lua端的分析工具,也蛮好用的,不过lu ...
- jdbc 报错解决办法
刚刚看到一个童鞋出现了这个问题 其实这个问题很好解决 在工程中创建一个lib目录: 然后讲mysql包复制进去 然后对着包点击右键 build path就可以了 最后面再次运行就可以了 jar包地址下 ...
- DAY2-JAVA
2018-1-28学习笔记 1.在开发中定义类.方法时也可以先添加文档注释,再用javadoc工具生成自己的API文档.Java文档注释和java工具使用. 2.掌握查阅java JDK和API文档. ...
- react-native入坑随笔(持续更新中)
一.问题: 解决方案:删除./node_modules/react-native/local-cli/core/__fixtures__/files/package.json,删除前记得备份. 二.在 ...
- 总结MySQL大数据量下如何进行优化
写在建库前: 在确定数据库业务后.建立数据库表格时,就应对一些常见问题有所考虑,以避免在数据增长一段时间后再做应对,可能造成时间及维护成本增加: 数据的月增量,年增量 数据的快速增长点 是否需要触发器 ...