简体   繁体   中英

Get video from webcam using FFmpeg Libav

I am trying to record webcam video using FFmpeg C libraries (libav), on a Mac computer. I made changes to the transcode.c example so that it opens a device instead of a file. However, for some reason the code only receives a single packet and then closes.

static int open_input_source(const char *dev_name) {
int ret;
unsigned int i;
AVDictionary *p_av_options = NULL;
AVInputFormat *p_av_input_format = av_find_input_format("avfoundation");
av_dict_set(&p_av_options, "framerate", "30", 0);

ifmt_ctx = NULL;
if ((ret = avformat_open_input(&ifmt_ctx, dev_name, p_av_input_format, &p_av_options) < 0)) {
    av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n");
    return ret;
}

if ((ret = avformat_find_stream_info(ifmt_ctx, NULL)) < 0) {
    av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n");
    return ret;
}

stream_ctx = av_calloc(ifmt_ctx->nb_streams, sizeof(*stream_ctx));
if (!stream_ctx)
    return AVERROR(ENOMEM);

for (i = 0; i < ifmt_ctx->nb_streams; i++) {
    AVStream *stream = ifmt_ctx->streams[i];
    const AVCodec *dec = avcodec_find_decoder(stream->codecpar->codec_id);
    AVCodecContext *codec_ctx;
    if (!dec) {
        av_log(NULL, AV_LOG_ERROR, "Failed to find decoder for stream #%u\n", i);
        return AVERROR_DECODER_NOT_FOUND;
    }
    codec_ctx = avcodec_alloc_context3(dec);
    if (!codec_ctx) {
        av_log(NULL, AV_LOG_ERROR, "Failed to allocate the decoder context for stream #%u\n", i);
        return AVERROR(ENOMEM);
    }
    ret = avcodec_parameters_to_context(codec_ctx, stream->codecpar);
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "Failed to copy decoder parameters to input decoder context "
                                   "for stream #%u\n", i);
        return ret;
    }
    /* Reencode video & audio and remux subtitles etc. */
    if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO
        || codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
        if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO)
            codec_ctx->framerate = av_guess_frame_rate(ifmt_ctx, stream, NULL);
        /* Open decoder */
        ret = avcodec_open2(codec_ctx, dec, NULL);
        if (ret < 0) {
            av_log(NULL, AV_LOG_ERROR, "Failed to open decoder for stream #%u\n", i);
            return ret;
        }
    }
    stream_ctx[i].dec_ctx = codec_ctx;

    stream_ctx[i].dec_frame = av_frame_alloc();
        if (!stream_ctx[i].dec_frame)
            return AVERROR(ENOMEM);
    }

    av_dump_format(ifmt_ctx, 0, dev_name, 0);
    return 0;
}

I have looked for other code examples but they are all deprecated and no longer compile in updated FFmpeg.

Is there some missing setting in my open_input_source function? Alternatively, is the problem in using transcoding is my basis? Should I try to use some other example?

In general, is there is a C source code reference which fulfills my requirements?

Thanks

This is a pretty fleshed out example that might meet your requirements:

https://github.com/argvk/ffmpeg-examples/blob/master/dshow_capture_video.c

I don't think you need nearly as much code as is include there, but you might be able to just update lines 260 with how long you want it to run (that example is 300 frames) and line 83 to open your webcam (sounds like you've already successfully done this with ret = avformat_open_input(&ifmt_ctx, dev_name, p_av_input_format, &p_av_options) in your code.

There are lots of other options there which you might want to remove, keep, or change depending on the details which are not provided here. Unfortunately I don't have a simplified code sample I'm able to share on here, but this dshow example is doing everything I expect.

Hope it helps some.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM