Разбор текстовых данных между двумя фреймами jpeg в потоке mjpeg с использованием gstreamer / gstreamer-java - PullRequest
0 голосов
/ 31 августа 2011

Я создал поток mjpeg. У меня есть длина содержимого между двумя кадрами в формате JPEG [между нижним колонтитулом первого кадра и заголовком следующего кадра].

[MJPEG STREAM]
      |
      V
...
----------
JPEG FRAME
(Image)
----------
Content-length
(Text)
----------
JPEG FRAME
(Image)
----------
Content-length
(Text)
----------
JPEG FRAME
(Image)
----------
...
      |
      V

Я могу воспроизвести видео с помощью gstreamer-java, gstreamer C API и gst-launch. Однако я пытаюсь разобрать текст длины содержимого в gstreamer-java. Я пробовал "метатеги" , но это не дает нужного мне результата

Я играю поток mjpeg, который я создал следующим образом

gst-launch -v souphttpsrc location="<ip>:<port>/<cgi_bin folder>/<name>.cgi" do-timestamp=true is_live=true ! multipartdemux ! jpegdec ! ffmpegcolorspace ! autovideosink

Я пробовал метатеги, используя

gst-launch -v souphttpsrc location="<ip>:<port>/<cgi_bin folder>/<name>.cgi" do-timestamp=true is_live=true ! multipartdemux ! jpegdec ! fakesink -t

и это

gst-launch -v souphttpsrc location="<ip>:<port>/<cgi_bin folder>/<name>.cgi" do-timestamp=true is_live=true ! fakesink -t

Однако вывод этого медиа-конвейера выглядит примерно так:

/GstPipeline:pipeline0/GstFakeSink:fakesink0: last-message = "chain   ******* < (557568   
bytes, timestamp: 0:00:06.895505695, duration: none, offset: -1, offset_end: -1, flags: 
0) 0x9a82818"
/GstPipeline:pipeline0/GstFakeSink:fakesink0: last-message = "chain   ******* < (557568 
bytes, timestamp: 0:00:06.941328354, duration: none, offset: -1, offset_end: -1, flags: 
0) 0x9a6f6e0"

Как видно, нет контента-длины. :(. Я использую WireShark и вижу пакеты данных, содержащие контент-длину. Впоследствии я написал отдельный код Java (без плагинов gstreamer), и я могу проанализировать поток, чтобы получить длину контента. Однако это не идеальный метод, как я хочу длина содержимого соответствует точному кадру с учетом синхронизации.

Я написал тройники ранее для кода C API. Мне интересно, будет ли тройник работать в этом случае!

1 Ответ

0 голосов
/ 08 сентября 2011

Appsink пригодился. Трубопровод выглядит как

                         _ queue -> appsink -> parser 
                       /  
        video -> tee ->
                       \_ demux -> decoder -> ffmpegcolorspace -> autovideosink 

Фрагмент кода Java выглядит как

Сначала определите корзину для приложений

final AppSink appsink = (AppSink) ElementFactory.make("appsink", "appsink");

Тогда его свойства ...

appsink.set("emit-signals",true);
appsink.set("max-buffers",1);
//appsink.set("drop",true); //Make this non-blocking. 
                            //Meaning drop frames when queue is full

Тогда его функция ...

appsink.connect(new AppSink.NEW_BUFFER() {
@Override public void newBuffer(Element elem, Pointer userData) {
AppSink appsink = (AppSink) elem;
Buffer buffer = appsink.pullBuffer();  //get the stream data as an input to external 
                                       //applications

/*
// Create a character ByteBuffer
CharBuffer cbuf = byteBuffer.asCharBuffer();
*/

ByteBuffer byteBuffer = buffer.getByteBuffer();
byte[] bytearray = new byte[byteBuffer.remaining()];
byteBuffer.get(bytearray);
String s = new String(bytearray);
//InputStream is = new ByteArrayInputStream(bytearray);
// System.out.print(buffer.getSize()+"\n");
//  System.out.print(s+"\n");

//Do whatever with this buffer inside string here e.g. parsing text content

...

byteBuffer.clear();
buffer.dispose();
buffer = null;

}
});           

// ============================================= ==============================

Фрагмент кода C выглядит как

...
sink = gst_element_factory_make ("appsink", "Output");
g_assert (sink);

Тогда ...

...
gst_app_sink_set_max_buffers((GstAppSink*)sink, 100);
gst_app_sink_set_emit_signals ((GstAppSink*)sink, TRUE);
g_signal_connect (sink, "new-buffer",  G_CALLBACK(new_buffer), NULL);

Тогда ...

static GstFlowReturn new_buffer (GstAppSink *app_sink, gpointer user_data)
{
  char* pipe_name = (char*) user_data;
  GstBuffer* buffer = gst_app_sink_pull_buffer(app_sink);

//  g_debug("appsink buffer timestamp(%lli) size(%d)",
//          GST_BUFFER_TIMESTAMP(buffer),
//          GST_BUFFER_SIZE(buffer));

  g_print((char*)buffer);

  gst_buffer_unref(buffer);
  return GST_FLOW_OK;
}
...