天天看點

ffmpeg從網上儲存視訊流到本地檔案

DTS

解碼時間戳,這個時間戳的意義在于告訴播放器該在什麼時候解碼這一幀的資料

PTS

顯示時間戳這個時間戳用來告訴播放器該在什麼時候顯示這一幀的資料

dts 解碼參考時間,pts是預覽參考時間,

在沒有B幀的情況下,pts=dts

在有B幀的情況下 同一幀才可能帶有不同的dts 和pts

要等到下一幀才能解碼,但是顯示時間在前面

//記一些重要函數
//轉換時間基
AVFormatContext *inputContext=nullptr;
AVFormatContext *outputContext;
void av_packet_ts(AVPacket *pkt,AVRational src_tb,AVRational dst_tb)
{
  if(pkt->pts!=AV_NOPTS_VALUE)
      pkt->pts=av_rescale_q(pkt->pts,src_tb,dst_tb);
  if(pkt->dts!=AV_NOPTS_VALUE)
      pkt->dts=av_rescale_q(pkt->dts,src_tb,dst_tb);
   if(pkt->duration>)
      pkt->duration=av_rescale_q(pkt->duration,src_tb,dst_tb);
} 
int WritePacket(AVPacket *packet)
{
    auto inputStream=inputContext->stream[packet->stream_index];
    auto outputStream=outputContext->stream[packet->stream_index];
    avpacket_rescale_ts(packet.get(),inputStream->time_base,outputStream->time_base);
av_interleaved_write_frame(outputContext,packet.get());
}
//packet 就是裸流PES  有時間戳
av_init_packet(packet.get());
int ret=av_read_frame(inputContext,packet.get());
if(ret>=)
{
return packet;
}
int Openinput(string inputUrl)
{
 inputContext=avformat_alloc_context();
 int ret=avformat_open_input(&inputContext,inputUrl.c_str,nullptr,nullptr);
 if(ret<)
 {
 av_log(NULL,AV_LOG_ERROR,"Input file open input failed\n");
 }
 ret=avformat_find_stream_info(inputContext,nullptr);
 if(ret<)
 {
 av_log(NULL,AV_LOG_ERROR,"Find input file stream inform failed\n");
 }
 else
 {
 av_log(NULL,AV_LOG_FATAL,"open input file%s success\n",inputUrl.c_str());
 }
 retrun ret;
}
int OpenOutput(string outUrl)
{
int ret=avformat_alloc_output_context2(&outputContext,nullptr,"mpegts",outUrl.c_str());
if(ret<)
{
av_log(NULL,AV_LOG_ERROR,"open output context failed\n");
goto Error;
}
ret=avio_open2(&outputContext->pb,outUrl.c_str(),AVIO_FLAG_READ_WRITE,nullptr,nullptr);
if(ret<)
{
av_log(NULL,AV_LOG_ERROR,"open avio failed");
goto Error;
}
for(int i=;i<inputContext->nb_streams;i++)
{
AVStream *stream=avformat_naw_stream(outputContext->stream[i]->codec->codec);
ret=avcodec_copy_context(stream->codec,inputContext->stream[i]->codec);
if(ret<)
{
av_log(NULL,AV_LOG_ERROR,"copy codec context failed\n");
goto Error;
}
ret=avformat_write_header(outputContext,nullptr);
if(ret<)
{
av_log(NULL,AV_LOG_ERROR,"format write head failed");
goto Error;
}
av_log(NULL,AV_LOG_FATAL,"open output file success%s\n",outYrl.c_ctr);
return ret;
Error:
if(outputContext)
{
    for(int i=;i<outputContext->nb_streams;i++)
    {
    avcodec_close(outputContext->stream[i]->codec);
    }
    avformat_close_input(&outputContext);
}
return ret;
}