Get the problem of camera data when using the avdevice module

For the developers that use FFmpeg in their software.
Post Reply
lee18
Posts: 1
Joined: Sat Mar 30, 2019 1:45 am

Get the problem of camera data when using the avdevice module

Post by lee18 » Sat Mar 30, 2019 2:18 am

I use ffmpeg's "avdevice" module to read image data from the mac os camera. After getting the AVFrame, I will use the YUV data stored in the AVFrame. That is to say, the data property of the avframe should have three values in an array, but Finally, I found the data property of avframe, only one value in the array, see the following figure:
Image

code show as below:

Code: Select all

#include <stdio.h>
#define __STDC_CONSTANT_MACROS
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavdevice/avdevice.h>
#include <SDL2/SDL.h>
//Output YUV420P 
#define OUTPUT_YUV420P 1
//'1' Use Dshow 
//'0' Use VFW
#define USE_DSHOW 0

//Refresh Event
#define SFM_REFRESH_EVENT  (SDL_USEREVENT + 1)

#define SFM_BREAK_EVENT  (SDL_USEREVENT + 2)

int thread_exit = 0;

int sfp_refresh_thread(void *opaque) {
    thread_exit = 0;
    while (!thread_exit) {
        SDL_Event event;
        event.type = SFM_REFRESH_EVENT;
        SDL_PushEvent(&event);
        SDL_Delay(40);
    }
    thread_exit = 0;
    //Break
    SDL_Event event;
    event.type = SFM_BREAK_EVENT;
    SDL_PushEvent(&event);

    return 0;
}


//Show Dshow Device
void show_dshow_device() {
    AVFormatContext *pFormatCtx = avformat_alloc_context();
    AVDictionary *options = NULL;
    av_dict_set(&options, "list_devices", "true", 0);
    AVInputFormat *iformat = av_find_input_format("dshow");
    printf("========Device Info=============\n");
    avformat_open_input(&pFormatCtx, "video=dummy", iformat, &options);
    printf("================================\n");
}

//Show Dshow Device Option
void show_dshow_device_option() {
    AVFormatContext *pFormatCtx = avformat_alloc_context();
    AVDictionary *options = NULL;
    av_dict_set(&options, "list_options", "true", 0);
    AVInputFormat *iformat = av_find_input_format("dshow");
    printf("========Device Option Info======\n");
    avformat_open_input(&pFormatCtx, "video=Integrated Camera", iformat, &options);
    printf("================================\n");
}

//Show VFW Device
void show_vfw_device() {
    AVFormatContext *pFormatCtx = avformat_alloc_context();
    AVInputFormat *iformat = av_find_input_format("vfwcap");
    printf("========VFW Device Info======\n");
    avformat_open_input(&pFormatCtx, "list", iformat, NULL);
    printf("=============================\n");
}

//Show AVFoundation Device
void show_avfoundation_device() {
    AVFormatContext *pFormatCtx = avformat_alloc_context();
    AVDictionary *options = NULL;
    av_dict_set(&options, "list_devices", "true", 0);
    AVInputFormat *iformat = av_find_input_format("avfoundation");
    printf("==AVFoundation Device Info===\n");
    avformat_open_input(&pFormatCtx, "", iformat, &options);
    printf("=============================\n");
}


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

    AVFormatContext *pFormatCtx;
    int i, videoindex;
    AVCodecContext *pCodecCtx;
    AVCodec *pCodec;

    av_register_all();
    avformat_network_init();
    pFormatCtx = avformat_alloc_context();

    //Open File
    //char filepath[]="src01_480x272_22.h265";
    //avformat_open_input(&pFormatCtx,filepath,NULL,NULL)

    //Register Device
    avdevice_register_all();


    show_avfoundation_device();
    //Mac
    AVInputFormat *ifmt = av_find_input_format("avfoundation");
    //Avfoundation
    //[video]:[audio]
    if (avformat_open_input(&pFormatCtx, "Capture screen 0", ifmt, NULL) != 0) {
        printf("Couldn't open input stream.\n");
        return -1;
    }


    if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
        printf("Couldn't find stream information.\n");
        return -1;
    }
    videoindex = -1;
    for (i = 0; i < pFormatCtx->nb_streams; i++)
        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoindex = i;
            break;
        }
    if (videoindex == -1) {
        printf("Couldn't find a video stream.\n");
        return -1;
    }
    pCodecCtx = pFormatCtx->streams[videoindex]->codec;
    pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
    if (pCodec == NULL) {
        printf("Codec not found.\n");
        return -1;
    }
    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
        printf("Could not open codec.\n");
        return -1;
    }
    AVFrame *pFrame, *pFrameYUV;
    pFrame = av_frame_alloc();
    pFrameYUV = av_frame_alloc();
    //unsigned char *out_buffer=(unsigned char *)av_malloc(avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));
    //avpicture_fill((AVPicture *)pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
    //SDL----------------------------
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
        printf("Could not initialize SDL - %s\n", SDL_GetError());
        return -1;
    }

    SDL_Window *window = SDL_CreateWindow("播放视频", 0, 0, pCodecCtx->width, pCodecCtx->height, SDL_WINDOW_OPENGL);
    if (window == NULL) {
        printf("SDL: could not create window - exiting:%s\n", SDL_GetError());
        return -2;
    }

    SDL_Renderer *render = SDL_CreateRenderer(window, -1, 0);
    if (render == NULL) {
        return -3;
    }
//    SDL_PIXELFORMAT_IYUV
    SDL_Texture *texture = SDL_CreateTexture(render, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING,
                                             pCodecCtx->width, pCodecCtx->height);
    if (texture == NULL) {
        return -4;
    }

    SDL_Rect rect;
    rect.x = 0;
    rect.y = 0;
    rect.w = pCodecCtx->width;
    rect.h = pCodecCtx->height;
    //SDL End------------------------
    int ret, got_picture;

    AVPacket *packet = (AVPacket *) av_malloc(sizeof(AVPacket));
    FILE *fp_yuv = fopen("/Users/like/Downloads/output.yuv", "wb+");
    struct SwsContext *img_convert_ctx;
    img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width,
                                     pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
    //------------------------------
    SDL_Thread *video_tid = SDL_CreateThread(sfp_refresh_thread, NULL, NULL);
  
    //Event Loop
    SDL_Event event;

    for (;;) {
        //Wait
        SDL_WaitEvent(&event);
        if (event.type == SFM_REFRESH_EVENT) {
            //------------------------------
            if (av_read_frame(pFormatCtx, packet) >= 0) {
                if (packet->stream_index == videoindex) {
                    ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
                    if (ret < 0) {
                        printf("Decode Error.\n");
                        return -1;
                    }
                    if (got_picture) {
                        int y_size = pCodecCtx->width * pCodecCtx->height;
                        fwrite(pFrame->data[0],1,y_size,fp_yuv);    //Y
                        fwrite(pFrame->data[1],1,y_size/4,fp_yuv);  //U
                        fwrite(pFrame->data[2],1,y_size/4,fp_yuv);
                    }
                }
                av_free_packet(packet);
            } else {
                //Exit Thread
                thread_exit = 1;
            }
        } else if (event.type == SDL_QUIT) {
            thread_exit = 1;
        } else if (event.type == SFM_BREAK_EVENT) {
            break;
        }
    }
    sws_freeContext(img_convert_ctx);
    fclose(fp_yuv);
    SDL_Quit();
    //av_free(out_buffer);
    av_free(pFrameYUV);
    avcodec_close(pCodecCtx);
    avformat_close_input(&pFormatCtx);

    return 0;
}


Post Reply