Troubles with camera acquisition with Ffmpeg api

For the developers that use FFmpeg in their software.
Post Reply
emVee
Posts: 2
Joined: Wed Sep 05, 2018 8:30 am

Troubles with camera acquisition with Ffmpeg api

Post by emVee » Wed Sep 05, 2018 10:01 am

Hi everybody.

I am trying to write a code for acquiring an usb camera stream and then output it on the screen. Basically I have adapted the example code in http://hasanaga.info/how-to-capture-fra ... th-opencv/ for C as follows:

Code: Select all


#include <stdio.h>
#include <stdlib.h>

#define __STDC_CONSTANT_MACROS
#define __STDC_LIMIT_MACROS
#define UINT64_C
#define [email protected]

#include <unistd.h> /* Added by me for close(f_desw). */
#include "fcntl.h"
int f_desw;


#include <libavdevice/avdevice.h>
#include <libswscale/swscale.h>
#include <opencv2\highgui\highgui_c.h>
#include <opencv2\imgproc\imgproc_c.h>

int main(int argc, char *argv[])
{
    avdevice_register_all();
    avcodec_register_all();

    //ffmpeg -list_devices true -f dshow -i dummy
    //ffmpeg -f dshow -rtbufsize 64M -i "video=Logitech HD Webcam C525" -s 640x480 -f sdl2 -
    //ffmpeg -f dshow -i "video=Logitech HD Webcam C525" -s 640x480 -f sdl2 -
    const char  *filenameSrc = "video=Logitech HD Webcam C525";

    AVCodecContext  *pCodecCtx;
    AVFormatContext *pFormatCtx = avformat_alloc_context();
    AVCodec * pCodec;
    AVInputFormat *iformat = av_find_input_format("dshow");
    AVFrame *pFrame, *pFrameRGB;

    /* */
    //AVDictionary* opt = NULL;
    //av_dict_set(&opt, "pixel_format", "bgr24", 0);
    /* */

    if(avformat_open_input(&pFormatCtx,filenameSrc,iformat,&opt) != 0) return -12;
    if(avformat_find_stream_info(pFormatCtx, NULL) < 0)   return -13;
    av_dump_format(pFormatCtx, 0, filenameSrc, 0);
    int videoStream = 1;
    for(int i=0; i < pFormatCtx->nb_streams; i++)
    {
        if(pFormatCtx->streams[i]->codec->coder_type==AVMEDIA_TYPE_VIDEO)
        {
            videoStream = i;
            break;
        }
    }

    if(videoStream == -1) return -14;
    pCodecCtx = pFormatCtx->streams[videoStream]->codec;

    pCodec =avcodec_find_decoder(pCodecCtx->codec_id);
    if(pCodec==NULL) return -15; //codec not found

    if(avcodec_open2(pCodecCtx,pCodec,NULL) < 0) return -16;

    pFrame    = av_frame_alloc();
    pFrameRGB = av_frame_alloc();

    uint8_t *buffer;
    int numBytes;

    enum AVPixelFormat  pFormat = AV_PIX_FMT_BGR24;
    numBytes = avpicture_get_size(pFormat,pCodecCtx->width,pCodecCtx->height);
    buffer = (uint8_t *) av_malloc(numBytes*sizeof(uint8_t));
    avpicture_fill((AVPicture *) pFrameRGB,buffer,pFormat,pCodecCtx->width,pCodecCtx->height);

    int res;
    int frameFinished;
    AVPacket packet;
    while( (res = av_read_frame(pFormatCtx,&packet)) >=0 )
    {

        if(packet.stream_index == videoStream){

            avcodec_decode_video2(pCodecCtx,pFrame,&frameFinished,&packet);

            if(frameFinished){

                struct SwsContext * img_convert_ctx;
                img_convert_ctx = sws_getCachedContext(NULL,pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,   pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL,NULL);
                sws_scale(img_convert_ctx, ((AVPicture*)pFrame)->data, ((AVPicture*)pFrame)->linesize, 0, pCodecCtx->height, ((AVPicture *)pFrameRGB)->data, ((AVPicture *)pFrameRGB)->linesize);

                //OpenCV
                CvMat mat = cvMat(pFrame->height,pFrame->width,CV_8UC3,pFrameRGB->data[0]);
                cvShowImage("display", &mat);
                cvWaitKey(1);

                av_free_packet(&packet);
                sws_freeContext(img_convert_ctx);

            }

        }

    }

    /* */
    printf("%s\n", av_err2str(res));
    /* */

    av_free_packet(&packet);
    close(f_desw);
    avcodec_close(pCodecCtx);
    av_free(pFrame);
    av_free(pFrameRGB);
    avformat_close_input(&pFormatCtx);

    return 0;
}
Despite the fact that the original example works for the guy who posted it in the link, I always get I/O error whenever

Code: Select all

av_read_frame()
is called (it returns -5). I can achieve my goal via cli with

Code: Select all

ffmpeg -f dshow -i "video=Logitech HD Webcam C525" -s 640x480 -f sdl2 -
.

I am an ffmpeg newbie so it is likely I makes very stupid mistakes, however what looks strange to me is that via cli I specify an output (as far as I have understood) device with

Code: Select all

-f sdl2 -
while it is unclear to me how to input this option through appropriate api within the C code. However, the original code seems working without it. I have also tried to compile some examples which writes the output in a new file without success. Googling around does not seem also to provide any useful information at least that I can understand. Any help is really appreciated.

Regards.

emVee
Posts: 2
Joined: Wed Sep 05, 2018 8:30 am

Re: Troubles with camera acquisition with Ffmpeg api

Post by emVee » Wed Sep 12, 2018 10:26 am

I am still in trouble. I have also tried the code in https://github.com/argvk/ffmpeg-example ... re_video.c without succeed. I get the same error (I/O error, i.e. -5) when av_read_frame() is called (line 264). By the way, I am using mingw toolchain (with msys2) in windows 10 with eclipse.

Thank you and regards.

thomasp
Posts: 1
Joined: Mon Sep 17, 2018 9:39 pm

Re: Troubles with camera acquisition with Ffmpeg api

Post by thomasp » Mon Sep 17, 2018 9:55 pm

Hi,

I have the same error.

I am streaming in UDP an MPTS file containing 4 video streams and 4 audio streams.

I can decode and display the video (and decode the audio) without problems for about 5-30 seconds. Then av_read_frame returns -5 which means "I/O error".

If I ignore this error (I do nothing and I try to decode the next frame), frames decoding does not work any more (I get no frame).

Any idea why this happen? and how to fix it?

Thankx in advance!

Post Reply