这篇文章中讲解了怎么使用FFmpeg读取摄像头,包括Windows,Linux和Mac。经过测试,发现在Mac 下avformat_open_input总是出错,提示Input/Output error。后来发现对于Mac下通过avfoudmation读取摄像头,需要提前设置framerate和video_size。正确的代码如下:

#include <iostream>
extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include <libavdevice/avdevice.h>
}

using namespace std;

int main(int argc, const char *argv[]) {
  int ret = 0;
  int videoStreamIndex = -1;
  AVFormatContext *s = NULL;
  AVDictionary *options = NULL;
  AVCodecParameters *par = NULL;
  AVCodec *codec;
  AVCodecContext *cctx;

  av_register_all();
  avdevice_register_all();

  AVInputFormat *ifmt = av_find_input_format("avfoundation");

  av_dict_set(&options, "framerate", "30", 0);
  av_dict_set(&options, "video_size", "1280x720", 0);
  ret = avformat_open_input(&s, "0", ifmt, &options);
  if (ret < 0) {
    cout << av_err2str(ret) << endl;
    goto error;
  }

  ret = avformat_find_stream_info(s, NULL);
  if (ret < 0) {
    cout << av_err2str(ret) << endl;
    goto error;
  }

  for (uint i = 0; i < s->nb_streams; i++) {
    if (s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
      videoStreamIndex = i;
      break;
    }
  }

  if (-1 == videoStreamIndex) {
    cout << "can't find video stream" << endl;
    goto error;
  }

  par = s->streams[videoStreamIndex]->codecpar;
  codec = avcodec_find_decoder(par->codec_id);
  cctx = avcodec_alloc_context3(codec);
  avcodec_parameters_to_context(cctx, par);

  ret = avcodec_open2(cctx, codec, NULL);
  if (ret < 0) {
    cout << av_err2str(ret) << endl;
    goto error;
  }

error:
  if (s) {
    avformat_free_context(s);
  }

  if (cctx) {
    avcodec_free_context(&cctx);
  }

  if (options) {
    av_dict_free(&options);
  }

  return ret;
}
问题是framerate和video_size是怎么来的呢?虽然可以通过list_devices的日志输出可以看到提示,但是在libavdevice(avdevice.h)中定义的一些API,对于avfoundation都是未实现的操作,不能通过

avdevice_capabilities_create查询设备的能力参数。



Logo

更多推荐