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是全局变量,如果有问题,请联系我。350197870

时间: 2024-08-10 21:28:49

ffmpeg 从视频流中抓取图片的相关文章

Phantomjs+Nodejs+Mysql数据抓取(2.抓取图片)

概要 这篇博客是在上一篇博客Phantomjs+Nodejs+Mysql数据抓取(1.抓取数据) http://blog.csdn.net/jokerkon/article/details/50868880 后进行的第二部分,请各位读者在看这篇博客之前先浏览上一篇,因为这里面有部分代码会沿用到上一部分的抓取结果. 好,现在开始正式的抓取图片的讲解 首先,我们先来看看代码: var page =require('webpage').create(); var address='http://pro

网络爬虫(专门抓取图片)

xmfdsh我真是兴趣多多,怎么老是静不下心来搞定一方面的技术,再学点其他的东西,循序渐进,好吧,我又研究网络爬虫去了,这是一个简单版的,参考了网上很多资料,C#来编写,专门抓取图片,能够抓取一些需要cookie的网站,所以功能上还是挺完善的,xmfdsh只研究了三天,因此还有大把需要改进的地方,日后再 慢慢改进,在本文后面附上整个项目,在此献给喜欢研究C#的朋友们,让我慢慢地道来: #region 访问数据 + Request(int index) /// <summary> /// 访问数

ffmpeg 从内存中读取数据

http://blog.csdn.net/leixiaohua1020/article/details/12980423 ffmpeg一般情况下支持打开一个本地文件,例如"C:\test.avi" 或者是一个流媒体协议的URL,例如"rtmp://222.31.64.208/vod/test.flv" 其打开文件的函数是avformat_open_input(),直接将文件路径或者流媒体URL的字符串传递给该函数就可以了. 但其是否支持从内存中读取数据呢?这个问题困

altera公司FPGA的视频流帧抓取

我们在用FPGA对视频进行处理时,常常会遇到:有时候图像中的某些文字显示模糊----这有可能是缩放导致:有时可能是AD/DA模块采用了不同厂家的芯片----导致转换后的效果不同:有可能在图像YUV422与YUV420互相转换----算法间接导致图像效果变差.林林总总,当然还有其它不同的图像处理而有可能降低画质的场景.在针对图像质量跟踪定位时,最直观的,莫过于直接抓取各图像处理功能模块的输入输出,取出前后图像直接对比,就能立竿见影的诊断出该模块是否异常.所以:如何在FPGA中抓取视频流中的一帧图像

python3用BeautifulSoup抓取图片地址

# -*- coding:utf-8 -*- #python 2.7 #XiaoDeng #http://tieba.baidu.com/p/2460150866 #抓取图片地址 from bs4 import BeautifulSoup import urllib.request html_doc = "http://tieba.baidu.com/p/2460150866" req = urllib.request.Request(html_doc) webpage = urlli

java练习题(字符串类):显示4位验证码、输出年月日、从XML中抓取信息

1.显示4位验证码 注:大小写字母.数字混合 public static void main(String[] args) { String s="abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";//设定验证码的集合 String s1=""; for(int i=0;i<4;i++){ int n=(int)(Math.random()*1000)%s.length();//取余

#在FLAT模式下,需要设置flat子网,VM的IP从这个设置的子网中抓取,这时flat_injected需要设置为True,系统才能自动获得IP,如果flat

#在FLAT模式下,需要设置flat子网,VM的IP从这个设置的子网中抓取,这时flat_injected需要设置为True,系统才能自动获得IP,如果flat子网和主机网络是同一网络,网络管理员要注意手动配置主机IP,以免IP冲突. #在FLATDHCP模式下,系统将通过自己的服务为VM分配IP,这时不要将flat_injected设置为True,同时设置flat_network_dhcp_start以防止IP冲突,我想这个参数应该是区别主机IP和VM的IP的. 注: 可以使用下列方法来控制I

网页中抓取数据

下面写个例子,实现从网页中抓取数据. 这个例子中,只是从网页中获取了数据,但是没有进行任何处理,只是将数据保存到一个txt文件中. 该例子是在android工程中写的. package com.example.creepertest; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.I

curl 抓取图片

/** * curl 抓取图片 * @param $url * @return mixed */ public static function downLoadImage($url) { $header = array('Expect:'); $ch = curl_init(); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET'); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt(