本文全部是在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. \n");
return EXIT_FAILURE;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
printf("Could't find stream infomation.\n");
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.\n");
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. \n");
return EXIT_FAILURE;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
printf("Could't find stream infomation.\n");
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.\n");
return EXIT_FAILURE;
}
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL) {
printf("Codec not found.\n");
return EXIT_FAILURE;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
printf("Could not open codec.\n");
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. \n");
return EXIT_FAILURE;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
printf("Could't find stream infomation.\n");
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.\n");
return EXIT_FAILURE;
}
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL) {
printf("Codec not found.\n");
return EXIT_FAILURE;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
printf("Could not open codec.\n");
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. \n");
return EXIT_FAILURE;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
printf("Could't find stream infomation.\n");
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.\n");
return EXIT_FAILURE;
}
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL) {
printf("Codec not found.\n");
return EXIT_FAILURE;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
printf("Could not open codec.\n");
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. \n");
return EXIT_FAILURE;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
printf("Could't find stream infomation.\n");
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.\n");
return EXIT_FAILURE;
}
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL) {
printf("Codec not found.\n");
return EXIT_FAILURE;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
printf("Could not open codec.\n");
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.\n");
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. \n");
return EXIT_FAILURE;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
printf("Could't find stream infomation.\n");
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.\n");
return EXIT_FAILURE;
}
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL) {
printf("Codec not found.\n");
return EXIT_FAILURE;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
printf("Could not open codec.\n");
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.\n");
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\n%d %d\n255\n", 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. \n");
return EXIT_FAILURE;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
printf("Could't find stream infomation.\n");
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.\n");
return EXIT_FAILURE;
}
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL) {
printf("Codec not found.\n");
return EXIT_FAILURE;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
printf("Could not open codec.\n");
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.\n");
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\n%d %d\n255\n", 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. \n");
return EXIT_FAILURE;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
printf("Could't find stream infomation.\n");
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.\n");
return EXIT_FAILURE;
}
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL) {
printf("Codec not found.\n");
return EXIT_FAILURE;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
printf("Could not open codec.\n");
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 \n", 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\n");
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.\n");
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;
}