GstAppSrc для больших буферов - PullRequest
0 голосов
/ 18 сентября 2018

Мой конвейер:

appsrc ! identity ! rtpvrawpay ! udpsink

Буферы, передаваемые в appsrc, представляют собой 640 * 480 необработанных RGBA32-несжатых байтовых массивов со скоростью 30 кадров в секунду - что ужасно медленно .Я использую элемент identity, чтобы измерить, как часто он получает кадры из appsrc, используя

g_signal_connect(data->identity, "handoff", cb_identity_handoff, data);

При 640 * 480 необработанных 32-битных RGBA без сжатия элемент identity получает кадры с ~2fps.Все сохранилось, 320 * 240 необработанных кадров дают около 12 кадров в секунду, а при 160 * 120 это дает полные 30 кадров в секунду.Это известная проблема с GstAppSrc?


Дополнительная информация:

Нет кадров, отбрасываемых на appsrc.Они все в очереди;Я проверил, используя GST_BUFFER_PTS, чтобы увидеть, удаляются ли какие-либо кадры, установив их, нажимая на appsrc, и прочитав их в identity.

Код:

Настройка AppSrc:

data->src = gst_bin_get_by_name(GST_BIN(data->pipeline), "camsrc");

g_object_set(G_OBJECT(data->src), "caps",
             gst_caps_new_simple("video/x-raw",
                                 "format", G_TYPE_STRING, "RGBA",
                                 "width", G_TYPE_INT, 640,
                                 "height", G_TYPE_INT, 480,
                                 "framerate", GST_TYPE_FRACTION, 30, 1,
                                  NULL), NULL);

gint64 frame_size = 640*480*4;
gint64 queue_size = 100*640*480*4;

g_object_set(G_OBJECT(data->src),
             "stream-type", GST_APP_STREAM_TYPE_STREAM,
             "format", GST_FORMAT_TIME,
             "block", FALSE,
             "max-bytes", queue_size,
             "size", frame_size,
             "is-live", TRUE,
             NULL);

Кадры передаются из Java в C с помощью следующей функции:

static void gst_add_stream(JNIEnv *env, jobject thiz, jbyteArray buffer, jint size, jlong ptime,
                           jlong custom_data) {
    CustomData *data = (CustomData *) (jint) custom_data;//GET_CUSTOM_DATA (env, thiz, custom_data);
    if (!data || size == 0) return;

    GstBuffer *gstbuffer;
    GstMapInfo map;
    GstFlowReturn ret;

    GstClockTime timestamp = ptime;

    jbyte *pbuffer = (jbyte *) (*env)->GetByteArrayElements(env, buffer, 0);

    // though I'm doing a memcopy here, and allocating, I've measured the time and it doesn't seem to be taking more than 2ms. Using CLOCK_REALTIME 
    gstbuffer = gst_buffer_new_allocate(NULL, size, NULL);
    gst_buffer_map(gstbuffer, &map, GST_MAP_WRITE);
    memcpy((char *) map.data, pbuffer, (int) size);

    gst_buffer_unmap(gstbuffer, &map);

    GST_BUFFER_PTS(gstbuffer) = timestamp;
    LOGD("add_stream timestamp %"G_GUINT64_FORMAT, GST_BUFFER_PTS (gstbuffer));
    GST_BUFFER_DURATION(gstbuffer) = gst_util_uint64_scale_int(1, GST_SECOND, data->framerate);
    g_signal_emit_by_name(data->src, "push-buffer", gstbuffer, &ret);

    if (ret != GST_FLOW_OK) {
        g_debug("push buffer returned %d for %d bytes \n", ret, size);
    }

    (*env)->ReleaseByteArrayElements(env, buffer, pbuffer, 0);
    gst_buffer_unref(gstbuffer);

    return;
}

Обратный вызов идентификатора, который измеряет fps:

static void cb_identity_handoff (GstElement *identity, GstBuffer *buffer, CustomData *data) {
    frame_counter++;
    double diff = (now_ms() - last_time);
    if (diff > 1000){
        LOGD("add frames: %.2f", frame_counter / diff * 1000.0f);
        last_time = now_ms();
        frame_counter = 0;
    }
}

1 Ответ

0 голосов
/ 27 сентября 2018

Все ваши элементы работают в одном потоке.Поместите элемент queue в ваш конвейер, откуда все следующие элементы будут выполняться в другом потоке:

appsrc ! queue ! identity ! rtpvrawpay ! udpsink
...