6. 【视频采集实战】

1. 打开视频设备

  • 设置url,"0"表示使用摄像头,”1“表示录制桌面;
  • 需要设置分辨率、帧率、采样格式,每个设备支持的参数可能都不一样;

2. 将数据写入文件

  • 在从包里面取数据时候,要自己根据采样的格式计算正确的size,如yuv420 = 分辨率宽 x 分辨率高 x 1.5;

3. 实战代码

  • 打开设备
static AVFormatContext* open_device() {
    
    avdevice_register_all();
    
    AVFormatContext *ctx = NULL;
    AVDictionary *options = NULL;

    AVInputFormat *fmt = av_find_input_format("avfoundation");
    // 0 表示摄像头   1 表示录制桌面
    char *device_name = "0";
    // 设置分辨率
    av_dict_set(&options, "video_size", "640*480", 0);
    // 设置帧率
    av_dict_set(&options, "framerate", "29.97", 0);
    // 设置采样格式
    av_dict_set(&options, "pixel_format", "nv12", 0);
    
    
    int result = avformat_open_input(&ctx, device_name, fmt, &options);
    
    if (result < 0 ) {
        char error[1024];
        av_make_error_string(error, 1024, result);
        printf("打开设备失败:%s", error);
        return NULL;
    }
    isRecording = 1;
    
    return ctx;
    
}
  • 将采集的数据写入文件
void start_video_recorder(void) {
    
    AVFormatContext *fmt_ctx = NULL;
    fmt_ctx = open_device();
    if (!fmt_ctx) {
        goto __ERROR;
    }
    
    AVPacket *packet = NULL;
    packet = av_packet_alloc();
    if (!packet) {
        goto __ERROR;
    }
    char *path = "/Users/cunw/Desktop/learning/音视频学习/音视频文件/video_recoder.yuv";
    FILE *file = fopen(path, "wb+");
    
    int rst = 0;
    while (isRecording) {
        rst = av_read_frame(fmt_ctx, packet);
        if (rst == 0 && packet->size > 0) {
            printf("packet size is %d\n", packet->size);
            // 因为采样格式420 所以size = 640 * 480 * 1.5
            fwrite(packet->data, 640 * 480 * 1.5, 1, file);
            av_packet_unref(packet);
            
        } else if (rst == -EAGAIN) {
            av_usleep(1);
        }
    }
    
__ERROR:
    
    isRecording = 0;
    fflush(file);
    fclose(file);
    av_packet_free(&packet);
    avformat_close_input(&fmt_ctx);
}
  • 使用命令工具ffplay播放:ffplay -pixel_format nv12 -video_size 640x480 video_recoder.yuv

你可能感兴趣的:(6. 【视频采集实战】)