FFmpeg解码视频和SDL显示

/*************************************************************************
    > 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;
}

存在问题:播放速度不正常。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值