本文全部是在Ubuntu 14.04下使用Eclipse开发,本文假定你Eclipse已经安装好了CDT,以及安装好了FFmpeg和SDL。
解码流程详见上一篇博客[原]零基础学习视频解码之FFMpeg中比较重要的函数以及数据结构。
如何安裝FFmpeg详见上一篇博客:[原]零基础学习视频解码之安装ffmpeg
下图是解码流程图(全图):
本文详解如何在Eclipse中使用使用C来完成一个解码的过程并且将其解码出来的YUV图片保存下来:
一、新建一个C Project,添加相关库的支持:
Project->Properties->C/C++ General->Path and Symbols->Libraries->Add->avcode、avutil、avformat、swscale
二、在工程中引用相应的头文件:
/* ============================================================================ Name : VideoDecodeTutorial.c Author : clarck Version : Copyright : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */ #include <stdio.h> #include <stdlib.h> #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libavutil/pixfmt.h" #include "libswscale/swscale.h" int main(int argc, char* args[]) { puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */ return EXIT_SUCCESS; }
三、定义AVFormatContext、AVCodecContext、AVCodec
/* ============================================================================ Name : VideoDecodeTutorial.c Author : clarck Version : Copyright : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */ #include <stdio.h> #include <stdlib.h> #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libavutil/pixfmt.h" #include "libswscale/swscale.h" int main(int argc, char* args[]) { AVFormatContext *pFormatCtx; AVCodecContext *pCodecCtx; AVCodec *pCodec; int videoStream, i; return EXIT_SUCCESS; }
四、注册所有格式以及初始化AVFormatContext
/* ============================================================================ Name : VideoDecodeTutorial.c Author : clarck Version : Copyright : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */ #include <stdio.h> #include <stdlib.h> #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libavutil/pixfmt.h" #include "libswscale/swscale.h" int main(int argc, char* args[]) { AVFormatContext *pFormatCtx; AVCodecContext *pCodecCtx; AVCodec *pCodec; int videoStream, i; av_register_all(); pFormatCtx = avformat_alloc_context(); return EXIT_SUCCESS; }
五、打开一个视频文件,获取视频文件的流信息, 获取初始的视频流
/* ============================================================================ Name : VideoDecodeTutorial.c Author : clarck Version : Copyright : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */ #include <stdio.h> #include <stdlib.h> #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libavutil/pixfmt.h" #include "libswscale/swscale.h" int main(int argc, char* args[]) { AVFormatContext *pFormatCtx; AVCodecContext *pCodecCtx; AVCodec *pCodec; int videoStream, i; char filePath[] = "./src/a.mp4"; av_register_all(); pFormatCtx = avformat_alloc_context(); if (avformat_open_input(&pFormatCtx, filePath, NULL, NULL) != 0) { printf("can't open the file. "); return EXIT_FAILURE; } if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { printf("Could't find stream infomation. "); return EXIT_FAILURE; } videoStream = 1; for (i = 0; i < pFormatCtx->nb_streams; i++) { if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { videoStream = i; } } if (videoStream == -1) { printf("Didn't find a video stream. "); return EXIT_FAILURE; } return EXIT_SUCCESS; }
六、获得视频流编码内容,获取视频编码格式,用一个编码格式打开一个编码文件
/* ============================================================================ Name : VideoDecodeTutorial.c Author : clarck Version : Copyright : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */ #include <stdio.h> #include <stdlib.h> #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libavutil/pixfmt.h" #include "libswscale/swscale.h" int main(int argc, char* args[]) { AVFormatContext *pFormatCtx; AVCodecContext *pCodecCtx; AVCodec *pCodec; int videoStream, i; char filePath[] = "./src/a.mp4"; av_register_all(); pFormatCtx = avformat_alloc_context(); if (avformat_open_input(&pFormatCtx, filePath, NULL, NULL) != 0) { printf("can't open the file. "); return EXIT_FAILURE; } if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { printf("Could't find stream infomation. "); return EXIT_FAILURE; } videoStream = 1; for (i = 0; i < pFormatCtx->nb_streams; i++) { if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { videoStream = i; } } if (videoStream == -1) { printf("Didn't find a video stream. "); return EXIT_FAILURE; } pCodecCtx = pFormatCtx->streams[videoStream]->codec; pCodec = avcodec_find_decoder(pCodecCtx->codec_id); if (pCodec == NULL) { printf("Codec not found. "); return EXIT_FAILURE; } if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { printf("Could not open codec. "); return EXIT_FAILURE; } return EXIT_SUCCESS; }
七、申请内存用来作为图片文件(AVPicture)缓冲
/* ============================================================================ Name : VideoDecodeTutorial.c Author : clarck Version : Copyright : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */ #include <stdio.h> #include <stdlib.h> #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libavutil/pixfmt.h" #include "libswscale/swscale.h" int main(int argc, char* args[]) { AVFormatContext *pFormatCtx; AVCodecContext *pCodecCtx; AVCodec *pCodec; AVFrame *pFrame, *pFrameYUV; uint8_t *out_buffer; int videoStream, i, numBytes; char filePath[] = "./src/a.mp4"; av_register_all(); pFormatCtx = avformat_alloc_context(); if (avformat_open_input(&pFormatCtx, filePath, NULL, NULL) != 0) { printf("can't open the file. "); return EXIT_FAILURE; } if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { printf("Could't find stream infomation. "); return EXIT_FAILURE; } videoStream = 1; for (i = 0; i < pFormatCtx->nb_streams; i++) { if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { videoStream = i; } } if (videoStream == -1) { printf("Didn't find a video stream. "); return EXIT_FAILURE; } pCodecCtx = pFormatCtx->streams[videoStream]->codec; pCodec = avcodec_find_decoder(pCodecCtx->codec_id); if (pCodec == NULL) { printf("Codec not found. "); return EXIT_FAILURE; } if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { printf("Could not open codec. "); return EXIT_FAILURE; } pFrame = av_frame_alloc(); pFrameYUV = av_frame_alloc(); numBytes = avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); out_buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t)); avpicture_fill((AVPicture *) pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); return EXIT_SUCCESS; }
八、为AVPacket申请内存
/* ============================================================================ Name : VideoDecodeTutorial.c Author : clarck Version : Copyright : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */ #include <stdio.h> #include <stdlib.h> #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libavutil/pixfmt.h" #include "libswscale/swscale.h" int main(int argc, char* args[]) { AVFormatContext *pFormatCtx; AVCodecContext *pCodecCtx; AVCodec *pCodec; AVFrame *pFrame, *pFrameYUV; AVPacket *packet; uint8_t *out_buffer;int videoStream, i, numBytes; int ret, got_picture; char filePath[] = "./src/a.mp4"; av_register_all(); pFormatCtx = avformat_alloc_context(); if (avformat_open_input(&pFormatCtx, filePath, NULL, NULL) != 0) { printf("can't open the file. "); return EXIT_FAILURE; } if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { printf("Could't find stream infomation. "); return EXIT_FAILURE; } videoStream = 1; for (i = 0; i < pFormatCtx->nb_streams; i++) { if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { videoStream = i; } } if (videoStream == -1) { printf("Didn't find a video stream. "); return EXIT_FAILURE; } pCodecCtx = pFormatCtx->streams[videoStream]->codec; pCodec = avcodec_find_decoder(pCodecCtx->codec_id); if (pCodec == NULL) { printf("Codec not found. "); return EXIT_FAILURE; } if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { printf("Could not open codec. "); return EXIT_FAILURE; } pFrame = av_frame_alloc(); pFrameYUV = av_frame_alloc(); numBytes = avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); out_buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t)); avpicture_fill((AVPicture *) pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); int y_size = pCodecCtx->width * pCodecCtx->height; packet = (AVPacket *) malloc(sizeof(AVPacket)); av_new_packet(packet, y_size); av_dump_format(pFormatCtx, 0, filePath, 0); return EXIT_SUCCESS; }
九、从AVFrame中读取AVPacket,解码video得到YUV图像AVPicture
/* ============================================================================ Name : VideoDecodeTutorial.c Author : clarck Version : Copyright : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */ #include <stdio.h> #include <stdlib.h> #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libavutil/pixfmt.h" #include "libswscale/swscale.h" int main(int argc, char* args[]) { AVFormatContext *pFormatCtx; AVCodecContext *pCodecCtx; AVCodec *pCodec; AVFrame *pFrame, *pFrameYUV; AVPacket *packet; uint8_t *out_buffer; int videoStream, i, numBytes; int ret, got_picture; char filePath[] = "./src/a.mp4"; av_register_all(); pFormatCtx = avformat_alloc_context(); if (avformat_open_input(&pFormatCtx, filePath, NULL, NULL) != 0) { printf("can't open the file. "); return EXIT_FAILURE; } if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { printf("Could't find stream infomation. "); return EXIT_FAILURE; } videoStream = 1; for (i = 0; i < pFormatCtx->nb_streams; i++) { if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { videoStream = i; } } if (videoStream == -1) { printf("Didn't find a video stream. "); return EXIT_FAILURE; } pCodecCtx = pFormatCtx->streams[videoStream]->codec; pCodec = avcodec_find_decoder(pCodecCtx->codec_id); if (pCodec == NULL) { printf("Codec not found. "); return EXIT_FAILURE; } if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { printf("Could not open codec. "); return EXIT_FAILURE; } pFrame = av_frame_alloc(); pFrameYUV = av_frame_alloc(); numBytes = avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); out_buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t)); avpicture_fill((AVPicture *) pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); int y_size = pCodecCtx->width * pCodecCtx->height; packet = (AVPacket *) malloc(sizeof(AVPacket)); av_new_packet(packet, y_size); av_dump_format(pFormatCtx, 0, filePath, 0); while (av_read_frame(pFormatCtx, packet) >= 0) { if (packet->stream_index == videoStream) { ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet); if (ret < 0) { printf("decode error. "); return EXIT_FAILURE; } if (got_picture) { //TODO 保存解码出来的图片 } } av_free_packet(packet); } av_free(out_buffer); av_free(pFrameYUV); avcodec_close(pCodecCtx); avformat_close_input(&pFormatCtx); return EXIT_SUCCESS; }
十、利用sws_scale將得到的YUV转换成Image data
/* ============================================================================ Name : VideoDecodeTutorial.c Author : clarck Version : Copyright : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */ #include <stdio.h> #include <stdlib.h> #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libavutil/pixfmt.h" #include "libswscale/swscale.h" int main(int argc, char* args[]) { AVFormatContext *pFormatCtx; AVCodecContext *pCodecCtx; AVCodec *pCodec; AVFrame *pFrame, *pFrameYUV; AVPacket *packet; uint8_t *out_buffer; static struct SwsContext *img_convert_ctx; int videoStream, i, numBytes; int ret, got_picture; char filePath[] = "./src/a.mp4"; av_register_all(); pFormatCtx = avformat_alloc_context(); if (avformat_open_input(&pFormatCtx, filePath, NULL, NULL) != 0) { printf("can't open the file. "); return EXIT_FAILURE; } if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { printf("Could't find stream infomation. "); return EXIT_FAILURE; } videoStream = 1; for (i = 0; i < pFormatCtx->nb_streams; i++) { if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { videoStream = i; } } if (videoStream == -1) { printf("Didn't find a video stream. "); return EXIT_FAILURE; } pCodecCtx = pFormatCtx->streams[videoStream]->codec; pCodec = avcodec_find_decoder(pCodecCtx->codec_id); if (pCodec == NULL) { printf("Codec not found. "); return EXIT_FAILURE; } if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { printf("Could not open codec. "); return EXIT_FAILURE; } pFrame = av_frame_alloc(); pFrameYUV = av_frame_alloc(); numBytes = avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); out_buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t)); avpicture_fill((AVPicture *) pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); int y_size = pCodecCtx->width * pCodecCtx->height; packet = (AVPacket *) malloc(sizeof(AVPacket)); av_new_packet(packet, y_size); av_dump_format(pFormatCtx, 0, filePath, 0); while (av_read_frame(pFormatCtx, packet) >= 0) { if (packet->stream_index == videoStream) { ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet); if (ret < 0) { printf("decode error. "); return EXIT_FAILURE; } if (got_picture) { img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); sws_scale(img_convert_ctx, (const uint8_t* const *) pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize); sws_freeContext(img_convert_ctx); //TODO 保存解码出来的图片 } } av_free_packet(packet); } av_free(out_buffer); av_free(pFrameYUV); avcodec_close(pCodecCtx); avformat_close_input(&pFormatCtx); return EXIT_SUCCESS; }
十一、将解码的data保存为.ppm
/* ============================================================================ Name : VideoDecodeTutorial.c Author : clarck Version : Copyright : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */ #include <stdio.h> #include <stdlib.h> #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libavutil/pixfmt.h" #include "libswscale/swscale.h" void SaveFrame(AVFrame *pFrame, int width, int height, int i) { FILE * pFile; char szFilename[32]; int y; sprintf(szFilename, "frame%d.ppm", i); pFile = fopen(szFilename, "wb"); if (pFile == NULL) { printf("pFile is null"); return; } fprintf(pFile, "P6 %d %d 255 ", width, height); for (y = 0; y < height; y++) { fwrite(pFrame->data[0] + y * pFrame->linesize[0], 1, width * 3, pFile); } fclose(pFile); } int main(int argc, char* args[]) { AVFormatContext *pFormatCtx; AVCodecContext *pCodecCtx; AVCodec *pCodec; AVFrame *pFrame, *pFrameYUV; AVPacket *packet; uint8_t *out_buffer; static struct SwsContext *img_convert_ctx; int videoStream, i, numBytes; int ret, got_picture; char filePath[] = "./src/a.mp4"; av_register_all(); pFormatCtx = avformat_alloc_context(); if (avformat_open_input(&pFormatCtx, filePath, NULL, NULL) != 0) { printf("can't open the file. "); return EXIT_FAILURE; } if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { printf("Could't find stream infomation. "); return EXIT_FAILURE; } videoStream = 1; for (i = 0; i < pFormatCtx->nb_streams; i++) { if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { videoStream = i; } } if (videoStream == -1) { printf("Didn't find a video stream. "); return EXIT_FAILURE; } pCodecCtx = pFormatCtx->streams[videoStream]->codec; pCodec = avcodec_find_decoder(pCodecCtx->codec_id); if (pCodec == NULL) { printf("Codec not found. "); return EXIT_FAILURE; } if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { printf("Could not open codec. "); return EXIT_FAILURE; } pFrame = av_frame_alloc(); pFrameYUV = av_frame_alloc(); numBytes = avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); out_buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t)); avpicture_fill((AVPicture *) pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); int y_size = pCodecCtx->width * pCodecCtx->height; packet = (AVPacket *) malloc(sizeof(AVPacket)); av_new_packet(packet, y_size); av_dump_format(pFormatCtx, 0, filePath, 0); while (av_read_frame(pFormatCtx, packet) >= 0) { if (packet->stream_index == videoStream) { ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet); if (ret < 0) { printf("decode error. "); return EXIT_FAILURE; } if (got_picture) { img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); sws_scale(img_convert_ctx, (const uint8_t* const *) pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize); sws_freeContext(img_convert_ctx); if (i < 20) { SaveFrame(pFrameYUV, pCodecCtx->width, pCodecCtx->height, ++i); } } } av_free_packet(packet); } av_free(out_buffer); av_free(pFrameYUV); avcodec_close(pCodecCtx); avformat_close_input(&pFormatCtx); return EXIT_SUCCESS; }
十二、将解码的数据使用SDL输出展现, 首先添加SDL库支持
Project->Properties->C/C++ General->Path and Symbols->Libraries->Add->SDL
/* ============================================================================ Name : VideoDecodeTutorial.c Author : clarck Version : Copyright : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */ #include <stdio.h> #include <stdlib.h> #include "SDL/SDL.h" #include "SDL/SDL_thread.h" #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libavutil/pixfmt.h" #include "libswscale/swscale.h" void SaveFrame(AVFrame *pFrame, int width, int height, int i) { FILE * pFile; char szFilename[32]; int y; sprintf(szFilename, "frame%d.ppm", i); pFile = fopen(szFilename, "wb"); if (pFile == NULL) { printf("pFile is null"); return; } fprintf(pFile, "P6 %d %d 255 ", width, height); for (y = 0; y < height; y++) { fwrite(pFrame->data[0] + y * pFrame->linesize[0], 1, width * 3, pFile); } fclose(pFile); } int main(int argc, char* args[]) { AVFormatContext *pFormatCtx; AVCodecContext *pCodecCtx; AVCodec *pCodec; AVFrame *pFrame, *pFrameYUV; AVPacket *packet; uint8_t *out_buffer; static struct SwsContext *img_convert_ctx; int videoStream, i, numBytes; int ret, got_picture; char filePath[] = "./src/a.mp4"; av_register_all(); pFormatCtx = avformat_alloc_context(); if (avformat_open_input(&pFormatCtx, filePath, NULL, NULL) != 0) { printf("can't open the file. "); return EXIT_FAILURE; } if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { printf("Could't find stream infomation. "); return EXIT_FAILURE; } videoStream = 1; for (i = 0; i < pFormatCtx->nb_streams; i++) { if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { videoStream = i; } } if (videoStream == -1) { printf("Didn't find a video stream. "); return EXIT_FAILURE; } pCodecCtx = pFormatCtx->streams[videoStream]->codec; pCodec = avcodec_find_decoder(pCodecCtx->codec_id); if (pCodec == NULL) { printf("Codec not found. "); return EXIT_FAILURE; } if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { printf("Could not open codec. "); return EXIT_FAILURE; } pFrame = av_frame_alloc(); pFrameYUV = av_frame_alloc(); numBytes = avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); out_buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t)); avpicture_fill((AVPicture *) pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); //==============SDL==================// if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) { printf("Could not initialize SDL - %s ", SDL_GetError()); exit(1); } SDL_Surface *screen; screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0); if (!screen) { printf("SDL:could not set video mode - exiting "); exit(1); } SDL_Overlay *bmp; bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height, SDL_YV12_OVERLAY, screen); SDL_Rect rect; //===================================// int y_size = pCodecCtx->width * pCodecCtx->height; packet = (AVPacket *) malloc(sizeof(AVPacket)); av_new_packet(packet, y_size); av_dump_format(pFormatCtx, 0, filePath, 0); while (av_read_frame(pFormatCtx, packet) >= 0) { if (packet->stream_index == videoStream) { ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet); if (ret < 0) { printf("decode error. "); return EXIT_FAILURE; } if (got_picture) { SDL_LockYUVOverlay(bmp); pFrameYUV->data[0] = bmp->pixels[0]; pFrameYUV->data[1] = bmp->pixels[2]; pFrameYUV->data[2] = bmp->pixels[1]; pFrameYUV->linesize[0] = bmp->pitches[0]; pFrameYUV->linesize[1] = bmp->pitches[2]; pFrameYUV->linesize[2] = bmp->pitches[1]; img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); sws_scale(img_convert_ctx, (const uint8_t* const *) pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize); sws_freeContext(img_convert_ctx); SDL_UnlockYUVOverlay(bmp); rect.x = 0; rect.y = 0; rect.w = pCodecCtx->width; rect.h = pCodecCtx->height; SDL_DisplayYUVOverlay(bmp, &rect); //delay 400ms SDL_Delay(400); } } av_free_packet(packet); } av_free(out_buffer); av_free(pFrameYUV); avcodec_close(pCodecCtx); avformat_close_input(&pFormatCtx); return EXIT_SUCCESS; }