#include
#include
//#include
using namespace std;
extern "C"
{
#include "SDL2/SDL.h"
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavutil/time.h"
};
AVFormatContext *inputContext;
AVFormatContext *outputContext;
int64_t lastreadtime;
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;
int ret = avformat_open_input(&inputContext,url.c_str(),NULL,NULL);
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)
{
int ret = avformat_alloc_output_context2(&outputContext,NULL,"singlejpeg",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_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,inputContext->streams[i]->codec->codec);
ret = avcodec_copy_context(avstream->codec,inputContext->streams[i]->codec);
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();
}
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_MJPEG);
(*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;
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;
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("http://ivi.bupt.edu.cn/hls/cctv5phd.m3u8");
if(ret >= 0)
{
ret = openOutput("1.jpg");
}
if( ret< 0)
return -1;
AVCodecContext *encodeContext = NULL;
InitDecodeContext(inputContext->streams[0]);
AVFrame *videoFrame = av_frame_alloc();
initEncoderCodec(inputContext->streams[0],&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);
if(ret >= 0)
{
break;
}
}
}
}
}
cout <<"Get Picture End "<
av_frame_free(&videoFrame);
avcodec_close(encodeContext);
Error:
CloseInput();
CloseOutput();
}