/*************************************************************************
> File Name: decode_video.c
> Author: charein
> Mail: chenyayun9@163.com
> Created Time: Sat 08 Feb 2014 08:20:16 PM CST
************************************************************************/
#include <stdio.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/mem.h>
#include <libswscale/swscale.h>
#include <SDL/SDL.h>
#include <SDL/SDL_thread.h>
static int sws_flags = SWS_BICUBIC;
void print_log(char *tag, char *text, char *key)
{
if (strcmp (key, "yes") != 0)
return;
printf("tag%s\n", text);
}
int main(int argc, char **argv)
{
AVFormatContext *pFormatCtx = NULL;
AVCodecContext *pCodecCtx; // 保存了 流 的 详细信细
AVCodec *pCodec; // 编解码 器
AVFrame *pFrame; // 保存数据 帧的 数据 结够构
AVPacket packet; //解析文件时会 将 音/视帧读入到 packet中
int videoStream = -1;
int audioStream = -1;
int i;
int frameFinished;
int numBytes;
uint8_t *buffer;
SDL_Overlay *bmp;
SDL_Surface *screen;
SDL_Rect rect;
SDL_Event event;
if (argc < 2)
{
fprintf(stderr, "error usage\n");
exit(1);
}
av_register_all(); //Init all support codec and decode
if (avformat_open_input(&pFormatCtx, argv[1], NULL, NULL) != 0) //
return -1;
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) //
return -1;
av_dump_format(pFormatCtx, -1, argv[1], 0); //print file info
printf("~~~~~~~~~~~~~~~~~~~~~\n");
// Find the first video stream
for (i=0; i<pFormatCtx->nb_streams; i++)
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStream = i;
break;
}
// Find the first audio stream
for (i=0; i<pFormatCtx->nb_streams; i++)
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
audioStream = i;
break;
}
if ((videoStream == -1) || (audioStream == -1))
return -1;
printf("videoStream : %d\naudioStream : %d\n", videoStream, audioStream);
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL) {
fprintf(stderr, "Unsupported codec!\n");
return -1;
}
//Open codec
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
return -1;
pFrame = avcodec_alloc_frame();
if (pFrame == NULL)
return -1;
numBytes = avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
buffer = (uint8_t)av_malloc(numBytes*sizeof(uint8_t));
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)){
fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
exit(1);
}
//创 建Surface
screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 24, 0);
if (!screen) {
fprintf(stderr, "SDL: could not set video mode - exiting\n");
exit(1);
}
//创 建一 个 YUV覆盖
bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height,\
SDL_YV12_OVERLAY, screen);
//变换 图像 格式
static struct SwsContext *img_convert_ctx;
if (img_convert_ctx == NULL) {
img_convert_ctx =sws_getContext(pCodecCtx->width, pCodecCtx->height, \
pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, \
PIX_FMT_YUV420P, sws_flags, NULL, NULL, NULL);
if (img_convert_ctx == NULL) {
fprintf(stderr, "Cannot initialize the conversion context\n");
exit(1);
}
}
//从 文件中 读取音 视频帧并 解码
while (av_read_frame(pFormatCtx, &packet) >= 0) {
if (packet.stream_index == videoStream) {
// Decode video frame
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
//frameFinished > 0 ,表 示解码 到 了 pFrame
if (frameFinished) {
SDL_LockYUVOverlay(bmp);
AVPicture pict;
pict.data[0] = bmp->pixels[0];
pict.data[1] = bmp->pixels[2];
pict.data[2] = bmp->pixels[1];
pict.linesize[0] = bmp->pitches[0];
pict.linesize[1] = bmp->pitches[2];
pict.linesize[2] = bmp->pitches[1];
// Convert the image into YUV format that SDL uses
sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, \
0, pCodecCtx->height, pict.data, pict.linesize);
SDL_UnlockYUVOverlay(bmp);
rect.x = 0;
rect.y = 0;
rect.w = pCodecCtx->width;
rect.h = pCodecCtx->height;
SDL_DisplayYUVOverlay(bmp, &rect);
}
}
// else if (packet.stream_index == audioStream) {
// }
av_free_packet(&packet);
SDL_PollEvent(&event);
switch(event.type) {
case SDL_QUIT:
SDL_Quit();
break;
default: break;
}
}
// 释放图像 和 关 閉 文件
av_free(buffer);
av_free(pFrame);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
return 0;
}
存在问题:播放速度不正常。