c语言rtsp客户端拉流,ffmpeg RTSP流拉取

extern "C" {

#include "libavformat/avformat.h"

#include "libswscale/swscale.h"

#include "libswresample/swresample.h"

#include "libavutil/pixdesc.h"

#include "libavutil/mem.h"

}

using namespace std;

typedef enum {

SLPiecesErrorNone,

SLPiecesErrorOpenFile,

SLPiecesErrorStreamInfoNotFound,

SLPiecesErrorCodecNotFound,

SLPiecesErrorOpenCodec,

SLPiecesErrorAllocateFrame,

SLPiecesErroSetupScaler,

SLPiecesErroReSampler,

SLPiecesErroUnsupported,

} SLPiecesError;

class SLRtspDecoder{

public:

SLRtspDecoder();

~SLRtspDecoder();

public:

void regsterWindow(CAEAGLLayer *layer);

int starPlayVideo(std::string &path);

void stopPlayVideo();

private:

SLPiecesError avformatOpenInput(std::string &path);

SLPiecesError openVideoStream();

void closeVideoStream();

SLPiecesError openAVCodec(int videoStream);

int readDataFromNetwork(AVPacket &avPacket);

vector collectStreams(AVFormatContext *formatCtx, enum AVMediaType codecType);

void avStreamFPSTimeBase(AVStream *st, float defaultTimeBase, float *pFPS, float *pTimeBase);

private:

bool isHaveLayer;

float _fps;

float _videoTimeBase;

GLRender mGLRender;

CAEAGLLayer *mViewWindow;

private:

int _videoStream;

int _artworkStream;

bool _isFirstIFrame;

vector _videoStreams;

AVFormatContext *_formatCtx;

AVFrame *_videoFrame;

AVCodecContext *_videoCodecCtx;

};

#include "SLRtspDecoder.hpp"

SLRtspDecoder::SLRtspDecoder()

{

}

SLRtspDecoder::~SLRtspDecoder()

{

}

void SLRtspDecoder::regsterWindow(CAEAGLLayer *layer)

{

mViewWindow = layer;

}

int SLRtspDecoder::starPlayVideo(std::string &path)

{

//Step 1: Register all file formats and codec library.

av_register_all();

//Step 2: Open the network video stream.

avformat_network_init();

_isFirstIFrame = false;

//Step 3: AVFormat open input and get parameters(_formatCtx).

SLPiecesError errCode = this->avformatOpenInput(path);

if (errCode != SLPiecesErrorNone) {

return -1;

}

//Step4:Set avcodec with video stream.

SLPiecesError videoErr = this->openVideoStream();

if (videoErr != SLPiecesErrorNone) {

return -1;

}

AVPacket avPacket;

while (true){

this->readDataFromNetwork(avPacket);

}

return 0;

}

int SLRtspDecoder::readDataFromNetwork(AVPacket &avPacket)

{

int nRet = av_read_frame(_formatCtx, &avPacket);

if(nRet < 0){

clock_t now = clock();

while(clock() - now < 100);

return -1;

}

if (avPacket.stream_index ==_videoStream) {

//Return the number of bytes used: got_picture_ptr Zero if no frame could be decompressed,.

int gotFrame = 0;

int lenUseable = avcodec_decode_video2(_videoCodecCtx, _videoFrame, &gotFrame, &avPacket);

if (lenUseable <= 0 || gotFrame == 0) {

printf(0, "--->decode video error, skip packet.");

return -1;

}

//Find the first key frame.

if(!_isFirstIFrame && _videoFrame->key_frame){

_isFirstIFrame = true;

return -1;

}

if (_videoCodecCtx->width > 0 && _videoCodecCtx->height > 0 && !isHaveLayer) {

isHaveLayer = true;

mGLRender.setGLSurface(_videoCodecCtx->width, _videoCodecCtx->height, mViewWindow);

}

if(_videoCodecCtx->width > 0 && _videoCodecCtx->height > 0){

mGLRender.nativeGLRender(_videoFrame->data[0],_videoFrame->data[1],_videoFrame->data[2]);

}

}

av_free_packet(&avPacket);

return 0;

}

SLPiecesError SLRtspDecoder::avformatOpenInput(std::string &path)

{

//Allocate an AVFormatContext.

AVFormatContext *formatCtx = avformat_alloc_context();

if (!formatCtx){

return SLPiecesErrorOpenFile;

}

//Open an input stream and read the header. The codecs are not opened.

AVDictionary * opts = NULL;

int net = avformat_open_input(&formatCtx, path.c_str(), NULL, &opts);

if (net < 0) {

if (formatCtx){

avformat_close_input(&formatCtx);

avformat_free_context(formatCtx);

}

return SLPiecesErrorOpenFile;

}

//Read packets of a media file to get stream information.

if (avformat_find_stream_info(formatCtx, NULL) < 0) {

avformat_close_input(&formatCtx);

return SLPiecesErrorStreamInfoNotFound;

}

//Print detailed information about the input or output format.

av_dump_format(formatCtx, 0, "1", false);

_formatCtx = formatCtx;

return SLPiecesErrorNone;

}

SLPiecesError SLRtspDecoder::openVideoStream()

{

_videoStream = -1;

_artworkStream = -1;

SLPiecesError errCode = SLPiecesErrorCodecNotFound;

_videoStreams = collectStreams(_formatCtx, AVMEDIA_TYPE_VIDEO);

for (auto iter = _videoStreams.begin(); iter != _videoStreams.end(); iter ++) {

const int iStream = *iter;

if (0 == (_formatCtx->streams[iStream]->disposition & AV_DISPOSITION_ATTACHED_PIC)) {

errCode = this->openAVCodec(iStream);

if (errCode == SLPiecesErrorNone){

break;

}

} else {

_artworkStream = iStream;

}

}

return errCode;

}

vector SLRtspDecoder::collectStreams(AVFormatContext *formatCtx, enum AVMediaType codecType)

{

vector streamVector;

for (int i = 0; i < formatCtx->nb_streams; ++i){

if (codecType == formatCtx->streams[i]->codec->codec_type){

streamVector.push_back(i);

}

}

return streamVector;

}

SLPiecesError SLRtspDecoder::openAVCodec(int videoStream)

{

// Find a registered decoder with a matching codec ID.

AVCodecContext *codecCtx = _formatCtx->streams[videoStream]->codec;

AVCodec *codec = avcodec_find_decoder(codecCtx->codec_id);

if (!codec){

return SLPiecesErrorCodecNotFound;

}

// Initialize the AVCodecContext to use the given AVCodec.

if (avcodec_open2(codecCtx, codec, NULL) < 0){

return SLPiecesErrorOpenCodec;

}

// Allocate an AVFrame and set its fields to default values.

_videoFrame = av_frame_alloc();

if (!_videoFrame) {

avcodec_close(codecCtx);

return SLPiecesErrorAllocateFrame;

}

// Calc fps

_videoStream = videoStream;

_videoCodecCtx = codecCtx;

AVStream *streamData = _formatCtx->streams[_videoStream];

avStreamFPSTimeBase(streamData, 0.04, &_fps, &_videoTimeBase);

return SLPiecesErrorNone;

}

void SLRtspDecoder::avStreamFPSTimeBase(AVStream *st, float defaultTimeBase, float *pFPS, float *pTimeBase)

{

float fps, timebase;

if (st->time_base.den && st->time_base.num){

timebase = av_q2d(st->time_base);

}else if(st->codec->time_base.den && st->codec->time_base.num){

timebase = av_q2d(st->codec->time_base);

}else{

timebase = defaultTimeBase;

}

if (st->codec->ticks_per_frame != 1) {

timebase *= st->codec->ticks_per_frame;

}

if (st->avg_frame_rate.den && st->avg_frame_rate.num){

fps = av_q2d(st->avg_frame_rate);

}else if (st->r_frame_rate.den && st->r_frame_rate.num){

fps = av_q2d(st->r_frame_rate);

}else{

fps = 1.0 / timebase;

}

if (pFPS){

*pFPS = fps;

}

if (pTimeBase){

*pTimeBase = timebase;

}

}

void SLRtspDecoder::stopPlayVideo(){

this->closeVideoStream();

if (_formatCtx) {

avformat_close_input(&_formatCtx);

_formatCtx = NULL;

}

}

void SLRtspDecoder::closeVideoStream()

{

_videoStream = -1;

if (_videoFrame) {

//av_free(_videoFrame);

_videoFrame = NULL;

}

if (_videoCodecCtx) {

avcodec_close(_videoCodecCtx);

_videoCodecCtx = NULL;

}

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值