ffmpeg 從視頻流中抓取圖片


從視頻中不斷抓取圖片的基本流程:打開視頻流地址->獲取視頻流packt->解碼成圖片幀->輸出圖片

一.初始化Ffmpeg

void ffmpegInit()
{
av_register_all(); avformat_network_init(); av_log_set_level(AV_LOG_ERROR);
}

  如果你不想輸出log,設置log級別為AV_LOG_PANIC。

二.打開視頻。

int Open(char* url)
{
    context = avformat_alloc_context(); 
     context->interrupt_callback.opaque = this; //C++
     context->interrupt_callback.callback = interruptCallback;//設置回調函數,否則有可能ffmpeg一直被掛住。 
     context->start_time_realtime = av_gettime();

    AVDictionary* options = nullptr; av_dict_set(
&options, "rtsp_transport", "udp", 0); //以udp方式打開,如果以tcp方式打開將udp替換為tcp av_dict_set(&options, "stimeout", "3000000", 0);  //設置超時斷開連接時間  int ret = avformat_open_input(&context, url, nullptr, &options); //avformat_open_input 返回0表示open成功,小於0表示open失敗
   if(ret < 0) return ret;
   ret = avformat_find_stream_info(context, options); ///avformat_find_stream_info 返回0表示查抄stream info成功 小於0表示失敗。
    if(options!= nullptr)
    {
       av_dict_free(options);
    }
   return ret;   }
int interrupt_cb(void *ctx) 
{ 
if((av_gettime() - ffmpeg->lastFrameRealtime) > 10 * 1000 * 1000) //10s超時退出
    {
         return AVERROR_EOF;
    }
     return 0;            
 } 

三 .讀取視頻包:

shared_ptr<AVPacket> ReadPacket()
{
    shared_ptr<AVPacket> packet((AVPacket*)av_malloc(sizeof(AVPacket)),   [&](AVPacket *p){av_free_packet(p);av_freep(&p);});
    av_init_packet(packet.get());
    lastFrameRealtime = av_gettime();
    int ret = av_read_frame(context, packet.get());
   if(ret >= 0)
   {
        return packet;
   }
   else 
   {
        return nullptr;
   }
}

  說明一下:不一定要用智能指針。我確定這樣寫不會有內存泄露,所以就不改了,隨手寫的代碼會有bug。

四. 解碼

    1. 初始化解碼器

InitDecoderCodec
{
   int ret = -1;
   for(int i = 0;  i < context->nb_streams; ++i)
{ AVCodecContext
*codecContext = context->streams[i]->codec; if(codecContext->codec_type == AVMEDIA_TYPE_VIDEO) {
      //返回小於0,打開解碼器失敗 ret = avcodec_open2(codecContext, avcodec_find_decoder(codecContext->codec_id), &options); }
}
return ret; }

   2. 解碼視頻包

AVFrame* DecodeVideoPacket(AVCodecContext* codecContext)
{
AVFrame* videoFrame = av_frame_alloc();
auto hr = avcodec_decode_video2(codecContext, frame, &gotFrame, packet); if(hr >= 0 && gotFrame != 0)
{
    return videoFrame;
}
   else
   {
    avcodec_free_frame(&videoFrame);
    return nullptr
   }
}

輸出圖片:

  uint8_t *GetPictureData(int width,int height, int *bufferSize)
{
pFrameYUV= av_frame_alloc(); uint8_t *out_buffer; out_buffer = new uint8_t[avpicture_get_size(PIX_FMT_RGB32, width, height)]; avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_RGB32, width, height); sws_scale(sws, (const uint8_t* const*)frame->data, frame->linesize, 0, height, pFrameYUV->data, pFrameYUV->linesize);
*bufferSize = width * height * 4;
  return pFrameYUV->data[0];
}

 context是全局變量,如果有問題,加群流媒體/Ffmpeg/音視頻 127903734或者766718184進行交流

視頻下載地址:http://www.chungen90.com/?news_3/

 Demo下載地址: http://www.chungen90.com/?news_2


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM