ffmpeg 拉实时流

#include
#include
#include  


//#include


using namespace std;


extern "C"
{


#include "SDL2/SDL.h"
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavutil/time.h"
#include "libavdevice/avdevice.h"












};


AVFormatContext *inputContext;
AVFormatContext *outputContext;
int64_t lastreadtime;
int64_t packetCount = 0;


static int interrupt_cb(void *ctx)
{
int timeout = 10;
if(av_gettime() -lastreadtime >  timeout *1000*1000)
{
return -1;
}
return 0;

}
int  readPacketFromSoursce(AVPacket *packet )
{
lastreadtime = av_gettime();
return av_read_frame(inputContext,packet);
}
int writePacket(AVPacket* packet)
{
AVStream *inputstream = inputContext->streams[packet->stream_index];
AVStream  *outputstream = outputContext->streams[packet->stream_index];
av_packet_rescale_ts(packet,inputstream->time_base,outputstream->time_base);
return av_interleaved_write_frame(outputContext,packet);
}
int openInput(string url)
{
inputContext = avformat_alloc_context();
lastreadtime = av_gettime();
inputContext->interrupt_callback.callback = interrupt_cb;
AVInputFormat *ifmt = av_find_input_format("video4linux2");
AVDictionary *format_opts =  NULL;
av_dict_set_int(&format_opts, "rtbufsize", 18432000  , 0);
int ret = avformat_open_input(&inputContext, url.c_str(), ifmt, &format_opts);
if(ret < 0)
{
printf(" %s %d %s\n",__FUNCTION__,__LINE__,"avformat_open_input error\n");
return ret;
}
ret = avformat_find_stream_info(inputContext,NULL);
if(ret < 0)
{
printf(" %s %d %s\n",__FUNCTION__,__LINE__,"avformat_find_stream_info error\n");
}
else
{
printf(" %s %d open url %s  sucess\n",__FUNCTION__,__LINE__,url.c_str());
}
return ret;
}


int openOutput(string url,AVCodecContext *encodeCodec)
{
int ret = avformat_alloc_output_context2(&outputContext,NULL,"flv",url.c_str());
if(ret < 0)
{
printf(" %s %d %s\n",__FUNCTION__,__LINE__,"avformat_alloc_output_context2 error\n");
goto Error;
}
ret = avio_open2(&outputContext->pb,url.c_str(),AVIO_FLAG_READ_WRITE,NULL,NULL);
if(ret < 0)
{
printf(" %s %d %s\n",__FUNCTION__,__LINE__,"avio_open2 error\n");
goto Error;
}
for(int i = 0; i < inputContext->nb_streams; i++)
{
if(inputContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
{
continue;
}
AVStream * avstream = avformat_new_stream(outputContext,encodeCodec->codec);
ret = avcodec_copy_context(avstream->codec,encodeCodec);
if(ret < 0)
{
printf(" %s %d %s\n",__FUNCTION__,__LINE__,"avcodec_copy_context error\n");
goto Error;
}
}
ret = avformat_write_header(outputContext,NULL);
{
if(ret < 0)
{
printf(" %s %d %s\n",__FUNCTION__,__LINE__,"avformat_write_header error\n");
goto Error;
}
}
printf(" %s %d open outURL %s suess\n",__FUNCTION__,__LINE__,url.c_str());
return ret;
Error :
if(outputContext)
{
for(int i = 0; i < outputContext->nb_streams; i++)
{
avcodec_close(outputContext->streams[i]->codec);
}
avformat_close_input(&outputContext);
}
return ret;
}
void init()
{
av_register_all();
avformat_network_init();
avdevice_register_all();
}
void CloseInput()
{
if(inputContext != NULL)
{
avformat_close_input(&inputContext);
}
}


void CloseOutput()
{
if(outputContext != NULL)
{
int ret = av_write_trailer(outputContext);
for(int i = 0 ; i < outputContext->nb_streams; i++)
{
AVCodecContext *codecContext = outputContext->streams[i]->codec;
avcodec_close(codecContext);
}
avformat_close_input(&outputContext);
}
}




int InitDecodeContext(AVStream *inputStream)
{
AVCodecID codecId = inputStream->codec->codec_id;
AVCodec *codec = avcodec_find_decoder(codecId);
if (!codec)
{
return -1;
}


int ret = avcodec_open2(inputStream->codec, codec, NULL);
return ret;


}


int initEncoderCodec(AVStream* inputStream,AVCodecContext **encodeContext)
{
AVCodec *  picCodec;

picCodec = avcodec_find_encoder(AV_CODEC_ID_H264);
(*encodeContext) = avcodec_alloc_context3(picCodec);

(*encodeContext)->codec_id = picCodec->id;
(*encodeContext)->time_base.num = inputStream->codec->time_base.num;
(*encodeContext)->time_base.den = inputStream->codec->time_base.den;
(*encodeContext)->pix_fmt =  *picCodec->pix_fmts;
(*encodeContext)->width = inputStream->codec->width;
(*encodeContext)->height =inputStream->codec->height;
(*encodeContext)->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
int ret = avcodec_open2((*encodeContext), picCodec, NULL);
if (ret < 0)
{
cout <<"open video codec failed \n";
return  ret;
}
return 1;
}


bool Decode(AVStream* inputStream,AVPacket* packet, AVFrame *frame)
{
int gotFrame = 0;
int  hr = avcodec_decode_video2(inputStream->codec, frame, &gotFrame, packet);
if (hr >= 0 && gotFrame != 0)
{
return true;
}
return false;
}


bool  Encode(AVCodecContext *encodeContext,AVFrame * frame,AVPacket * pkt)
{
int gotOutput = 0;
// packet 初始化不然会报错
av_init_packet(pkt);
pkt->data = NULL;
pkt->size = 0;
frame->pts = frame->pkt_dts = frame->pkt_pts = 40 * packetCount;
int ret = avcodec_encode_video2(encodeContext, pkt, frame, &gotOutput);
if (ret >= 0 && gotOutput)
{
return true;
}
else
{
return false;
}
}




int main(int argc,char *argv[])
{
init();
int ret  = openInput("/dev/video0");
if( ret< 0)
return -1;
AVCodecContext *encodeContext = NULL;
InitDecodeContext(inputContext->streams[0]);
AVFrame *videoFrame = av_frame_alloc();
initEncoderCodec(inputContext->streams[0],&encodeContext);
if(ret >= 0)
{
ret = openOutput("udp://127.0.0.1:1234",encodeContext);
}
AVPacket pkt,pkt1;
memset(&pkt, 0, sizeof(AVPacket));
av_init_packet(&pkt);
av_init_packet(&pkt1);
while(true)
{
ret =  readPacketFromSoursce(&pkt);
if(pkt.stream_index == 0)
{
if(Decode(inputContext->streams[0],&pkt,videoFrame))
{
printf("%s %d\n",__FUNCTION__,__LINE__);
if(Encode(encodeContext,videoFrame,&pkt))
{
ret = writePacket(&pkt);

}


}

}
}
cout <<"Get Picture End "< av_frame_free(&videoFrame);
avcodec_close(encodeContext);
Error:
CloseInput();
CloseOutput();
}

你可能感兴趣的:(ffmpeg)