使用高通的gstreamer qtiqmmfsrc和qt实现照相机应用

1. 高通提供了qtiqmmfsrc的模块来获取摄像头数据

2. qt中执行下列代码打开摄像头

GstElement \*pipeline = gst_parse_launch("qtiqmmfsrc camera=0 ! video/x-raw(memory:GBM),format=NV12,width=1920,height=1080,framerate=30/1 ! videoconvert ! appsink drop=1 name=appsink", nullptr);
GstElement \*appsink = gst_bin_get_by_name(GST_BIN(pipeline), "appsink");

3. 将图像显示到预览QLabel控件的逻辑

GstSample *sample = gst_app_sink_pull_sample(GST_APP_SINK(appsink));

if (sample) {

    GstBuffer *buffer = gst_sample_get_buffer(sample);

    GstMapInfo map;

    if (gst_buffer_map(buffer, &map, GST_MAP_READ)) {

        if (width == 0) {

            GstCaps *caps = gst_sample_get_caps(sample);

            if (caps) {

                GstStructure *structure = gst_caps_get_structure(caps, 0);

                if (structure) {

                    gst_structure_get_int(structure, "width", &width);

                    gst_structure_get_int(structure, "height", &height);

                }

                gst_caps_unref(caps);

            }

        }

        int y_size = width * height;

        int crop_height = height - 20;

        int crop_y_size = width * crop_height;

        uint8_t *rgb_data = new uint8_t[width * crop_height * 3];

        SwsContext *sws_ctx = sws_getContext(width, crop_height, AV_PIX_FMT_NV12, width, crop_height, AV_PIX_FMT_RGB24, SWS_BILINEAR, NULL, NULL, NULL);

        int srcStride[2] = {width, width};

        int dstStride[1] = {width * 3};

        uint8_t *srcSlice[2] = {map.data + (20 * width), map.data + y_size + (20 * width / 2)};

        sws_scale(sws_ctx, srcSlice, srcStride, 0, crop_height, &rgb_data, dstStride);

        QImage image(rgb_data, width, crop_height, width * 3, QImage::Format_RGB888);

        int new_width = 800;

        int new_height = static_cast<int>(static_cast<double>(crop_height) * (new_width / static_cast<double>(width)));

        QImage scaledImage = image.scaled(new_width, new_height, Qt::KeepAspectRatio, Qt::SmoothTransformation);

        previewLabel->setPixmap(QPixmap::fromImage(scaledImage));

        delete[] rgb_data;

        sws_freeContext(sws_ctx);

        gst_buffer_unmap(buffer, &map);

    }

    gst_sample_unref(sample);

}

4. 拍照保存jpg图片的逻辑

GstSample *sample = gst_app_sink_pull_sample(GST_APP_SINK(appsink));

if (sample) {

    GstBuffer *buffer = gst_sample_get_buffer(sample);

    GstMapInfo map;

    if (gst_buffer_map(buffer, &map, GST_MAP_READ)) {

        if (width == 0) {

            GstCaps *caps = gst_sample_get_caps(sample);

            if (caps) {

                GstStructure *structure = gst_caps_get_structure(caps, 0);

                if (structure) {

                    gst_structure_get_int(structure, "width", &width);

                    gst_structure_get_int(structure, "height", &height);

                }

                gst_caps_unref(caps);

            }

        }

        int y_size = width * height;

        int crop_height = height - 20;

        int crop_y_size = width * crop_height;

        uint8_t *rgb_data = new uint8_t[width * crop_height * 3];

        SwsContext *sws_ctx = sws_getContext(width, crop_height, AV_PIX_FMT_NV12, width, crop_height, AV_PIX_FMT_RGB24, SWS_BILINEAR, NULL, NULL, NULL);

        int srcStride[2] = {width, width};

        int dstStride[1] = {width * 3};

        uint8_t *srcSlice[2] = {map.data + (20 * width), map.data + y_size + (20 * width / 2)};

        sws_scale(sws_ctx, srcSlice, srcStride, 0, crop_height, &rgb_data, dstStride);

        QImage image(rgb_data, width, crop_height, width * 3, QImage::Format_RGB888);

        QImage scaledImage = image.scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);

        QString fileName = QString("IMG_%1.jpg").arg(QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss"));

        scaledImage.save(fileName);

        delete[] rgb_data;

        sws_freeContext(sws_ctx);

        gst_buffer_unmap(buffer, &map);

    }

    gst_sample_unref(sample);

}