基于ffmpeg+SDL2 实现简单rtsp播放器

参考资料:

编译参考:         http://blog.chinaunix.net/uid-20718335-id-2980793.html

代码参考:         http://blog.csdn.net/leixiaohua1020/article/details/8652605

实现ffmpeg在window下编译,并基于ffmpeg动态库用测试程序播放本地文件和RTSP视频流

csdn博客插个图片怎么这么麻烦,上篇辛辛苦苦截了那么多图一上传全没了,代码里想变色结果发布了一看全成HTML掺在程序里了,真是无语。。。

1、下载安装MinGW,http://sourceforge.net/projects/mingw/下载安装MinGW Installation Manager,选择mingw-develop-toolkit、mingw32-base、mingw32-gcc-g++、mysys-base,然后Apply Changes

2、进入到MinGW安装目录,默认是C:\MInGW,编辑C:\MinGW\msys\1.0\msys.bat,在文件开始加上 call "C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat" 根据具体VS路径,保存。

3、下载ffmpeg http://www.ffmpeg.org/releases/ 选择最新版本,当前是ffmpeg-2.2.4.tar.gz

下载yasm  http://yasm.tortall.net/Download.html(ffmpeg汇编编译器)

下载mp3lame http://sourceforge.net/projects/lame/files/(支持MP3)

下载x264 http://www.videolan.org/developers/x264.html(支持264)

下载SDL2 http://www.libsdl.org/release/SDL2-devel-2.0.3-VC.zip (SDL 多媒体开发库,用来显示,因此直接下载已编译好的)

另外几个可选项:

Xxid  http://www.xvid.org/

faad2 http://www.audiocoding.com/downloads.html

faac http://www.audiocoding.com/downloads.html

aacenc http://sourceforge.net/projects/opencore-amr/files/

amr-nb amr-wb http://www.penguin.cz/~utx/amr

opencore-amr http://sourceforge.net/projects/opencore-amr/files/

4、解压yasm,将exe放到c:\windows\system32下

解压ffmpeg,并将上面的第三方包分别解压到ffmpeg文件夹下

运行mysys.bat

安装mp3lame

cd lame-3.99.2
./configure --disable-shared
make
make install

安装x264

cd x264-snapshot-20140703-2245
./configure --enable-shared
make
make install

安装其他第三方库同上

默认安装到C:\MinGW\msys\1.0\local下

安装ffmpeg

cd ffmpeg-2.2.4
./configure --enable-shared --disable-static --enable-ffplay --enable-nonfree --enable-memalign-hack --enable-libmp3lame --enable-gpl --enable-libx264 --enable-version3 --extra-cflags=-IC:/MinGW/msys/1.0/local/include --extra-ldflags=-LC:/MinGW/msys/1.0/local/lib
make
make install

make install时出现错误:

C:\MinGW\bin\strip.exe: unable to rename ‘C:/MinGW/msys/1.0/local/bin/avcodec-55

.dll‘; reason: File exists

后来发现将360关了就好了

OK,烦人的编译过程已经结束,接下来就可以愉快的写测试demo了

==================================================================================================================================

1、VS2010建立VC++  win32控制台项目

2、在工程目录下建立lib目录和include目录,将已编译好的lib拷打lib下,include拷到include下,dll拷到Debug目录下,sdl2解压编译好的文件拷贝到相应目录

3、工程属性--配置属性--VC++目录--包含目录,添加ffmpeg头文件目录及其他第三方头文件目录

链接器--常规--附加库目录,添加lib目录

链接器--输入--附加依赖项,添加各个lib名

4、在include下新建文本文档 添加#define FFMPEG_VERSION "2.2.4" 并保存为version.h

5、添加ffmpeg-test.cpp

// ffmpeg-test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#ifdef __cplusplus
extern "C" {
#endif

#include <avcodec.h>
#include <avdevice.h>
#include <avformat.h>
#include <avfilter.h>
#include <avutil.h>
#include <swscale.h>
#include <SDL/SDL.h>

#ifdef __cplusplus
}
#endif

int _tmain(int argc, _TCHAR* argv[])
{
	AVFormatContext	*pFormatCtx;
	int				i, videoindex;
	AVCodecContext	*pCodecCtx;
	AVCodec			*pCodec;
	char filepath[]="nwn.mp4";
	//char rtspUrl[] = "rtsp://192.168.11.19/live0.264";
	//char rtspUrl[] = "rtsp://218.204.223.237:554/live/1/0547424F573B085C/gsfp90ef4k0a6iap.sdp";
	char rtspUrl[] = "rtsp://211.139.194.251:554/live/2/13E6330A31193128/5iLd2iNl5nQ2s8r8.sdp";
	av_register_all();//注册组件
	avformat_network_init();//支持网络流
	pFormatCtx = avformat_alloc_context();//初始化AVFormatContext
	if(avformat_open_input(&pFormatCtx,/*filepath*/rtspUrl,NULL,NULL)!=0){//打开文件
		printf("无法打开文件\n");
		return -1;
	}
	if(av_find_stream_info(pFormatCtx)<0)//查找流信息
	{
		printf("Couldn't find stream information.\n");
		return -1;
	}
	videoindex=-1;
	for(i=0; i<pFormatCtx->nb_streams; i++) //获取视频流ID
		if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
		{
			videoindex=i;
			break;
		}
	if(videoindex==-1)
	{
		printf("Didn't find a video stream.\n");
		return -1;
	}
	pCodecCtx=pFormatCtx->streams[videoindex]->codec;
	pCodec=avcodec_find_decoder(pCodecCtx->codec_id);//查找解码器
	if(pCodec==NULL)
	{
		printf("Codec not found.\n");
		return -1;
	}
	if(avcodec_open2(pCodecCtx, pCodec, NULL)<0)//打开解码器
	{
		printf("Could not open codec.\n");
		return -1;
	}
	AVFrame	*pFrame,*pFrameYUV;
	pFrame=avcodec_alloc_frame();//存储解码后AVFrame
	pFrameYUV=avcodec_alloc_frame();//存储转换后AVFrame(为什么要转换?后文解释)
	uint8_t *out_buffer;
	out_buffer=new uint8_t[avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height)];//分配AVFrame所需内存
	avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);//填充AVFrame

	//------------SDL初始化--------
	if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
		printf( "Could not initialize SDL - %s\n", SDL_GetError());
		return -1;
	}
	SDL_Window *screen = SDL_CreateWindow("RTSP Client Demo",
                          SDL_WINDOWPOS_UNDEFINED,
                          SDL_WINDOWPOS_UNDEFINED,
                          pCodecCtx->width, pCodecCtx->height,
                          SDL_WINDOW_RESIZABLE/* SDL_WINDOW_HIDDEN*/| SDL_WINDOW_OPENGL);
	if(!screen) {
		printf("SDL: could not set video mode - exiting\n");
		return -1;
	}
	SDL_Renderer* sdlRenderer = SDL_CreateRenderer(screen, -1, 0);
    SDL_Texture* sdlTexture = SDL_CreateTexture(
        sdlRenderer,
        SDL_PIXELFORMAT_YV12,
        SDL_TEXTUREACCESS_STREAMING,
        pCodecCtx->width,
        pCodecCtx->height); 

	SDL_Rect rect;
	//-----------------------------
	int ret, got_picture;
	static struct SwsContext *img_convert_ctx;
	int y_size = pCodecCtx->width * pCodecCtx->height;

	SDL_Event event;
	AVPacket *packet=(AVPacket *)malloc(sizeof(AVPacket));//存储解码前数据包AVPacket
	av_new_packet(packet, y_size);
	//输出一下信息-----------------------------
	printf("文件信息-----------------------------------------\n");
	av_dump_format(pFormatCtx,0,filepath,0);
	printf("-------------------------------------------------\n");
	//------------------------------
	while(av_read_frame(pFormatCtx, packet)>=0)//循环获取压缩数据包AVPacket
	{
		if(packet->stream_index==videoindex)
		{
			ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);//解码。输入为AVPacket,输出为AVFrame
			if(ret < 0)
			{
				printf("解码错误\n");
				return -1;
			}
			if(got_picture)
			{
				//像素格式转换。pFrame转换为pFrameYUV。
				img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, 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显示--------
				rect.x = 0;
				rect.y = 0;
				rect.w = pCodecCtx->width;
				rect.h = pCodecCtx->height;    

                SDL_UpdateTexture( sdlTexture, &rect, pFrameYUV->data[0], pFrameYUV->linesize[0] );
                SDL_RenderClear( sdlRenderer );
                SDL_RenderCopy( sdlRenderer, sdlTexture, &rect, &rect );
                SDL_RenderPresent( sdlRenderer );
				//延时40ms
				SDL_Delay(20);
				//------------SDL-----------
			}
		}
		av_free_packet(packet);
		SDL_PollEvent(&event);
        switch( event.type ) {
            case SDL_QUIT:
                SDL_Quit();
                exit(0);
                break;
            default:
                break;
        }
	}

	SDL_DestroyTexture(sdlTexture);
	delete[] out_buffer;
	av_free(pFrameYUV);
	avcodec_close(pCodecCtx);
	avformat_close_input(&pFormatCtx);

	return 0;
}

参考了网上的资料并做了修改,主要是ffmpeg接口和SDL2接口的改变,SDL2改动的接口参照 http://wiki.libsdl.org/MigrationGuide,ffmpeg改动的接口在源码目录下的doc\APIchanges文件

基于ffmpeg+SDL2 实现简单rtsp播放器,布布扣,bubuko.com

时间: 2024-10-20 22:31:31

基于ffmpeg+SDL2 实现简单rtsp播放器的相关文章

基于FFMPEG的裸眼3D播放器

整个裸眼3D显示是一个很大的项目,播放器只是其中的一个工具.至于标题中的裸眼3D,并不是噱头.需要3D片源+3D播放器+3D显示器,出来的效果还是很赞的.这篇文章里,先说说播放器~当做写个总结,如果能遇到大牛给予些交流指正,也是极好的~ 话不多说,先上图: 这是整个播放器的框架,可以看到用了很多不同的模块. 1. 最顶层采用的是QT,因为QT的信号槽机制使用起来特别方便,上手也比较快. 2. 最底层采用的是FFMPEG,这个没啥好说的了,做播放器的都懂的~一开始啥也不会,都是看着雷霄骅老师的博客

ffmpeg学习(三)——ffmpeg+SDL2 实现简单播放器

本篇实现基于ffmpeg动态库用测试程序播放本地文件和RTSP视频流. 参考文章:http://blog.csdn.net/leixiaohua1020/article/details/8652605, http://blog.csdn.net/guanghua2_0beta/article/details/37578299 创建工程,参考上一篇文章:http://www.cnblogs.com/wenjingu/p/3990071.html,注意:下载SDL2库的开发版,lib文件放到lib文

[SimplePlayer] 实现一个简单的播放器

简单的播放器需要实现一个最基本的功能:播放视频文件. 实现这个功能需要包含以下几个步骤: 从视频文件中提取视频图像 在屏幕上显示视频图像 视频帧的同步,也就是保证视频图像在合适的时间在屏幕上显示 从视频文件中提取音频 向音频设备输出音频 音频同步,也就是保证合适的时间输出合适的音频 多线程处理 音视频同步 本实现是通过ffmpeg来实现音视频的提取,通过sdl2来实现音视频的输出,版本如下: libavutil 56. 19.100 / 56. 19.100 libavcodec 58. 23.

Android开发---MediaPlayer简单音乐播放器

Android开发-MediaPlayer简单音乐播放器 功能介绍 实现一个简单的播放器,类似网易云音乐形式,功能包括: 播放.暂停,停止,退出功能: 后台播放功能: 进度条显示播放进度.拖动进度条改变进度功能: 播放时图片旋转,显示当前播放时间功能: 界面样式 功能实现 1. MediaPlayer的实现 MediaPlayer常用方法介绍 MediaPlayer的实现包括初始化MediaPlayer,MediaPlayer的功能实现,包括播放.暂停.停止.离开等,具体细节如下: MediaP

快速构建Windows 8风格应用21-构建简单媒体播放器

原文:快速构建Windows 8风格应用21-构建简单媒体播放器 本篇博文主要介绍如何构建一个简单的媒体播放器. <快速构建Windows 8风格应用20-MediaElement>博文中提到了如何使用MediaElement对象进行播放视频的简单功能,但是在实际应用中需要更复杂的功能,例如:控制视频播放的控件.全屏模式.进度条等等其他功能. 本篇博文中示例使用应用程序中包含的媒体文件,当然我们也可以通过网络或者本地[使用FileOpenPicker]进行加载某一媒体文件. MSDN中关于媒体

简单媒体播放器

// //  ViewController.m //  简单媒体播放器 // //  Created by 殷婷婷 on 15-6-12. //  Copyright (c) 2015年 lanou. All rights reserved. // #import "ViewController.h" #import <MediaPlayer/MediaPlayer.h> @interface ViewController () @property(nonatomic,st

Android开发6:Service的使用(简单音乐播放器的实现)

前言 啦啦啦~各位好久不见啦~博主最近比较忙,而且最近一次实验也是刚刚结束~ 好了不废话了,直接进入我们这次的内容~ 在这篇博文里我们将学习Service(服务)的相关知识,学会使用 Service 进行后台工作, 学会使用 Service 与 Activity 进行通信,并在此知识基础上学会使用 MediaPlayer和简单的多线程编程.使用 Handle 更新 UI,并设计成功一个简单的音乐播放器. 是不是很高大上呢~一起来学习~ 基础知识 Service作为Android四大组件之一,在每

Android 实现简单音乐播放器(一)

今天掐指一算,学习Android长达近两个月了,今天开始,对过去一段时间的学习收获以及遇到的疑难杂症做一些总结. 简单音乐播放器是我自己完成的第一个功能较为完整的APP,可以说是我的Android学习之路上的一个小小里程碑,给我增加了很多信心(~~真容易获得满足~~).从下面开始,我将详细介绍MusicPlayer的设计过程. 首先,先看一下这个项目的工程目录和运行效果:      从上面的图片看到,整个工程的布局文件有两个:activity_main.xml和musiclist.xml,其中,

Android——简单音乐播放器

使用MediaPlayer做的简单音乐播放器,更多内容请到百度经验查看   http://jingyan.baidu.com/article/60ccbceb63452364cab197f1.html <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:l