FFmpeg讀取Mac攝像頭的問題

摩西2016發表於2017-09-16

這篇文章中講解了怎麼使用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查詢裝置的能力引數。



相關文章