2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "mv_common.h"
18 #include "mv_video_helper.h"
20 #include "mv_log_cfg.h"
26 #include <gst/app/gstappsink.h>
27 #include <gst/video/video.h>
31 typedef struct _mv_video_reader_s {
35 /* Pipeline structure */
37 GstElement *decodebin;
38 GstElement *videoconvert;
42 void *new_sample_cb_user_data;
43 void *eos_cb_user_data;
48 pthread_spinlock_t new_sample_cb_guard;
49 pthread_spinlock_t eos_cb_guard;
51 mv_video_reader_new_sample_cb new_sample_cb;
52 mv_video_reader_eos_cb eos_cb;
55 typedef struct _mv_video_writer_s {
59 /* Pipeline structure */
61 GstElement *capsfilter;
62 GstElement *videoconvert;
68 image_data_s image_data;
70 unsigned int buffer_size;
73 /* video reader internal funcitons */
74 static int _mv_video_reader_create_internals(mv_video_reader_s *reader);
75 static int _mv_video_reader_link_internals(mv_video_reader_s *reader);
76 static int _mv_video_reader_state_change(mv_video_reader_s *reader, GstState state);
78 /* video writer internal funciton */
79 static int _mv_video_writer_create_internals(mv_video_writer_s *writer);
80 static int _mv_video_writer_link_internals(mv_video_writer_s *writer);
81 static int _mv_video_writer_state_change(mv_video_writer_s *writer, GstState state);
83 static void appsink_eos(GstAppSink *appsink, gpointer user_data);
84 static GstFlowReturn appsink_newsample(GstAppSink *appsink, gpointer user_data);
85 static void cb_newpad(GstElement *decodebin, GstPad *new_pad, gpointer user_data);
87 static GstPadProbeReturn pad_probe_data_cb(GstPad *pad, GstPadProbeInfo *info, gpointer user_data);
90 int mv_create_video_reader(
91 mv_video_reader_h *reader)
93 mv_video_reader_s *handle = NULL;
94 int err = MEDIA_VISION_ERROR_NONE;
97 LOGE("NULL pointer passed");
98 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
101 gst_init(NULL, NULL);
103 handle = (mv_video_reader_s *) malloc(sizeof(mv_video_reader_s));
105 LOGE("Not enough memory");
106 return MEDIA_VISION_ERROR_INVALID_OPERATION;
108 memset(handle, 0, sizeof(mv_video_reader_s));
110 err = _mv_video_reader_create_internals(handle);
111 if (MEDIA_VISION_ERROR_NONE != err) {
112 LOGE("Failed to create internals");
117 err = _mv_video_reader_link_internals(handle);
118 if (MEDIA_VISION_ERROR_NONE != err) {
119 LOGE("Failed to link internals");
124 *reader = (mv_video_reader_s *) handle;
129 int mv_destroy_video_reader(
130 mv_video_reader_h reader)
132 mv_video_reader_s *handle = NULL;
134 if (reader == NULL) {
135 LOGE("NULL pointer passed");
136 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
139 handle = (mv_video_reader_s *) reader;
141 if (handle->caps && GST_OBJECT_REFCOUNT(handle->caps))
142 gst_caps_unref(handle->caps);
145 gst_object_unref(handle->pl);
149 pthread_spin_destroy(&(handle->new_sample_cb_guard));
150 pthread_spin_destroy(&(handle->eos_cb_guard));
152 LOGD("video reader destroyed %p", handle);
156 return MEDIA_VISION_ERROR_NONE;
159 int mv_video_reader_load(
160 mv_video_reader_h reader,
162 image_data_s *image_data,
165 mv_video_reader_s *handle = NULL;
168 if (reader == NULL || path == NULL ||
169 image_data == NULL || fps == NULL) {
170 LOGE("NULL pointer passed");
171 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
174 handle = (mv_video_reader_s *) reader;
176 /* Set input file location from path */
177 g_object_set(G_OBJECT(handle->filesrc),
182 if (_mv_video_reader_state_change(handle, GST_STATE_PLAYING)) {
183 LOGE("Unable to change state");
184 return MEDIA_VISION_ERROR_INVALID_OPERATION;
187 if (_mv_video_reader_state_change(handle, GST_STATE_PAUSED)) {
188 LOGE("Unable to change state");
189 return MEDIA_VISION_ERROR_INVALID_OPERATION;
192 if (handle->caps == NULL) {
193 LOGE("Unable to get caps from decodebin");
194 return MEDIA_VISION_ERROR_INVALID_OPERATION;
197 gst_video_info_from_caps(&info, handle->caps);
199 gst_caps_unref(handle->caps);
201 *fps = info.fps_n/info.fps_d;
203 /* Fill image data */
204 image_data->image_width = info.width;
205 image_data->image_height = info.height;
208 * http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-libs/html/gst-plugins-base-libs-gstvideo.html#GstVideoFormat */
209 switch (GST_VIDEO_FORMAT_INFO_FORMAT(info.finfo)) {
210 case(GST_VIDEO_FORMAT_GRAY8):
211 image_data->image_colorspace = MEDIA_VISION_COLORSPACE_Y800;
213 case(GST_VIDEO_FORMAT_I420):
214 image_data->image_colorspace = MEDIA_VISION_COLORSPACE_I420;
216 case(GST_VIDEO_FORMAT_NV12):
217 image_data->image_colorspace = MEDIA_VISION_COLORSPACE_NV12;
219 case(GST_VIDEO_FORMAT_YV12):
220 image_data->image_colorspace = MEDIA_VISION_COLORSPACE_YV12;
222 case(GST_VIDEO_FORMAT_NV21):
223 image_data->image_colorspace = MEDIA_VISION_COLORSPACE_NV21;
225 case(GST_VIDEO_FORMAT_YUY2):
226 image_data->image_colorspace = MEDIA_VISION_COLORSPACE_YUYV;
228 case(GST_VIDEO_FORMAT_UYVY):
229 image_data->image_colorspace = MEDIA_VISION_COLORSPACE_UYVY;
231 case(GST_VIDEO_FORMAT_RGB):
232 image_data->image_colorspace = MEDIA_VISION_COLORSPACE_RGB888;
234 case(GST_VIDEO_FORMAT_RGBA):
235 image_data->image_colorspace = MEDIA_VISION_COLORSPACE_RGBA;
238 LOGE("Video pixel format is not supported\n");
239 return MEDIA_VISION_ERROR_NOT_SUPPORTED_FORMAT;
242 return MEDIA_VISION_ERROR_NONE;
245 int mv_video_reader_start(
246 mv_video_reader_h reader)
248 mv_video_reader_s *handle = NULL;
250 if (reader == NULL) {
251 LOGE("NULL pointer passed");
252 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
255 handle = (mv_video_reader_s *) reader;
258 if (_mv_video_reader_state_change(handle, GST_STATE_PLAYING)) {
259 LOGE("Unable to change state");
260 return MEDIA_VISION_ERROR_INVALID_OPERATION;
263 return MEDIA_VISION_ERROR_NONE;
266 int mv_video_reader_stop(
267 mv_video_reader_h reader)
269 mv_video_reader_s *handle = NULL;
271 if (reader == NULL) {
272 LOGE("NULL pointer passed");
273 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
276 handle = (mv_video_reader_s *) reader;
278 /* Stop playback (NULL or READY) */
279 if (_mv_video_reader_state_change(handle, GST_STATE_NULL)) {
280 LOGE("Unable to change state");
281 return MEDIA_VISION_ERROR_INVALID_OPERATION;
284 return MEDIA_VISION_ERROR_NONE;
287 int mv_video_reader_set_new_sample_cb(
288 mv_video_reader_h reader,
289 mv_video_reader_new_sample_cb callback,
292 mv_video_reader_s *handle = NULL;
294 if (reader == NULL || callback == NULL) {
295 LOGE("NULL pointer passed");
296 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
299 handle = (mv_video_reader_s *) reader;
301 pthread_spin_lock(&(handle->new_sample_cb_guard));
302 handle->new_sample_cb = callback;
303 handle->new_sample_cb_user_data = user_data;
304 pthread_spin_unlock(&(handle->new_sample_cb_guard));
306 return MEDIA_VISION_ERROR_NONE;
309 int mv_video_reader_set_eos_cb(
310 mv_video_reader_h reader,
311 mv_video_reader_eos_cb callback,
314 mv_video_reader_s *handle = NULL;
316 if (reader == NULL || callback == NULL) {
317 LOGE("NULL pointer passed");
318 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
321 handle = (mv_video_reader_s *) reader;
323 pthread_spin_lock(&(handle->eos_cb_guard));
324 handle->eos_cb = callback;
325 handle->eos_cb_user_data = user_data;
326 pthread_spin_unlock(&(handle->eos_cb_guard));
328 return MEDIA_VISION_ERROR_NONE;
332 int mv_create_video_writer(
333 mv_video_writer_h *writer)
335 mv_video_writer_s *handle = NULL;
336 int err = MEDIA_VISION_ERROR_NONE;
338 if (writer == NULL) {
339 LOGE("NULL pointer passed");
340 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
343 gst_init(NULL, NULL);
345 handle = (mv_video_writer_s *) malloc(sizeof(mv_video_writer_s));
347 LOGE("Not enough memory");
348 return MEDIA_VISION_ERROR_INVALID_OPERATION;
350 memset(handle, 0, sizeof(mv_video_writer_s));
352 err = _mv_video_writer_create_internals(handle);
353 if (MEDIA_VISION_ERROR_NONE != err) {
354 LOGE("Failed to create internals");
359 *writer = (mv_video_writer_s *) handle;
364 int mv_destroy_video_writer(
365 mv_video_writer_h writer)
367 mv_video_writer_s *handle = NULL;
369 if (writer == NULL) {
370 LOGE("NULL pointer passed");
371 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
374 handle = (mv_video_writer_s *) writer;
376 _mv_video_writer_state_change(writer, GST_STATE_NULL);
379 gst_object_unref(handle->pl);
383 LOGD("video writer destroyed %p", handle);
387 return MEDIA_VISION_ERROR_NONE;
390 int mv_video_writer_init(
391 mv_video_writer_h writer,
393 image_data_s image_data,
396 mv_video_writer_s *handle = NULL;
397 unsigned int err = MEDIA_VISION_ERROR_NONE;
399 if (writer == NULL) {
400 LOGE("NULL pointer passed");
401 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
404 handle = (mv_video_writer_s *) writer;
406 handle->image_data.image_width = image_data.image_width;
407 handle->image_data.image_height = image_data.image_height;
408 handle->image_data.image_colorspace = image_data.image_colorspace;
412 g_object_set(G_OBJECT(handle->filesink),
416 err = _mv_video_writer_link_internals(handle);
417 if (MEDIA_VISION_ERROR_NONE != err) {
418 LOGE("Failed to link internals");
425 int mv_video_writer_write_frame(
426 mv_video_writer_h writer,
427 unsigned char *frame)
429 mv_video_writer_s *handle = NULL;
431 GstBuffer *buffer = NULL;
433 if (writer == NULL || frame == NULL) {
434 LOGE("NULL pointer passed");
435 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
438 handle = (mv_video_writer_s *) writer;
440 buffer = gst_buffer_new_allocate(NULL, handle->buffer_size, NULL);
442 LOGE("Unable to allocate buffer for frame");
443 return MEDIA_VISION_ERROR_INVALID_OPERATION;
446 LOGD("Copying input frame to buffer and pushing to appsrc");
447 gst_buffer_map(buffer, &info, GST_MAP_READWRITE);
448 memcpy(info.data, frame, info.size);
449 gst_buffer_unmap(buffer, &info);
452 gst_app_src_push_buffer(handle->appsrc, buffer)) {
453 LOGE("Failed to push buffer to appsrc");
454 return MEDIA_VISION_ERROR_INVALID_OPERATION;
457 return MEDIA_VISION_ERROR_NONE;
460 /* Internal functions */
461 static int _mv_video_reader_create_internals(
462 mv_video_reader_s *reader)
464 pthread_spin_init(&(reader->new_sample_cb_guard), PTHREAD_PROCESS_SHARED);
465 pthread_spin_init(&(reader->eos_cb_guard), PTHREAD_PROCESS_SHARED);
467 reader->pl = gst_pipeline_new(NULL);
469 reader->filesrc = gst_element_factory_make("filesrc", "filesrc");
470 reader->decodebin = gst_element_factory_make("decodebin", "decoder");
471 reader->videoconvert = gst_element_factory_make("videoconvert", "convert");
472 reader->queue = gst_element_factory_make("queue", "queue");
473 reader->appsink = gst_element_factory_make("appsink", "appsink");
476 (!reader->filesrc) ||
477 (!reader->decodebin) ||
478 (!reader->videoconvert) ||
480 (!reader->appsink)) {
481 LOGE("Unable to create video read pipeline elements");
482 return MEDIA_VISION_ERROR_INVALID_OPERATION;
485 gst_bin_add_many(GST_BIN(reader->pl),
488 reader->videoconvert,
493 return MEDIA_VISION_ERROR_NONE;
496 static int _mv_video_reader_link_internals(
497 mv_video_reader_s *reader)
499 GstCaps *caps = NULL;
502 if (!gst_element_link_many(reader->filesrc,
505 LOGE("Unable to link filesrc to decodebin");
506 return MEDIA_VISION_ERROR_INVALID_OPERATION;
509 /* Decodebin pad will be linked during state change */
510 g_signal_connect(reader->decodebin,
512 G_CALLBACK(cb_newpad),
515 if (!gst_element_link_many(reader->videoconvert,
519 LOGE("Unable to link videocovnert-queue-appsink");
520 return MEDIA_VISION_ERROR_INVALID_OPERATION;
523 caps = gst_caps_new_simple("video/x-raw",
524 "format", G_TYPE_STRING, "RGB",
527 gst_app_sink_set_caps(GST_APP_SINK(reader->appsink), caps);
528 gst_caps_unref(caps);
530 /* Configure appsink */
531 gst_app_sink_set_emit_signals(GST_APP_SINK(reader->appsink), TRUE);
532 g_signal_connect(reader->appsink,
534 G_CALLBACK(appsink_newsample),
536 g_signal_connect(reader->appsink,
538 G_CALLBACK(appsink_eos),
540 g_object_set(G_OBJECT(reader->appsink),
542 "enable-last-sample", TRUE,
548 pad = gst_element_get_static_pad(reader->queue, "src");
550 gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER,
551 (GstPadProbeCallback)pad_probe_data_cb, reader, NULL);
552 gst_object_unref(pad);
554 return MEDIA_VISION_ERROR_NONE;
557 static int _mv_video_reader_state_change(
558 mv_video_reader_s *reader,
561 mv_video_reader_s *handle = (mv_video_reader_s *) reader;
562 GstStateChangeReturn state_ret = GST_STATE_CHANGE_FAILURE;
563 GstState pipeline_state = GST_STATE_NULL;
565 state_ret = gst_element_set_state(handle->pl,
568 if (GST_STATE_CHANGE_FAILURE == state_ret) {
569 LOGE("Set state failure");
570 return MEDIA_VISION_ERROR_INVALID_OPERATION;
573 LOGI("Set state [%d], change return [%d]",
576 state_ret = gst_element_get_state(handle->pl,
579 GST_CLOCK_TIME_NONE);
581 if (GST_STATE_CHANGE_FAILURE == state_ret) {
582 LOGE("get state failure");
583 return MEDIA_VISION_ERROR_INVALID_OPERATION;
586 return MEDIA_VISION_ERROR_NONE;
589 static int _mv_video_writer_create_internals(
590 mv_video_writer_s *writer)
592 writer->pl = gst_pipeline_new(NULL);
594 writer->appsrc = gst_element_factory_make("appsrc", "appsrc");
595 writer->capsfilter = gst_element_factory_make("capsfilter", NULL);
596 writer->videoconvert = gst_element_factory_make("videoconvert", "videoconvert");
597 writer->encoder = gst_element_factory_make("avenc_mpeg4", "encoder");
598 writer->queue = gst_element_factory_make("queue", "queue");
599 writer->muxer = gst_element_factory_make("avmux_avi", "muxer");
600 writer->filesink = gst_element_factory_make("filesink", "filesink");
604 (!writer->capsfilter) ||
605 (!writer->videoconvert) ||
606 (!writer->encoder) ||
609 (!writer->filesink)) {
610 LOGE("Unable to create video read pipeline elements\n");
611 return MEDIA_VISION_ERROR_INVALID_OPERATION;
614 gst_bin_add_many(GST_BIN(writer->pl),
617 writer->videoconvert,
624 return MEDIA_VISION_ERROR_NONE;
627 static int _mv_video_writer_link_internals(
628 mv_video_writer_s *writer)
631 GstCaps *caps = NULL;
632 char format[6] = {0};
634 /* Convert from mv_colorspace to GstVideoFormat */
635 switch (writer->image_data.image_colorspace) {
636 case(MEDIA_VISION_COLORSPACE_Y800):
637 strncpy(format, "GRAY8", 5);
639 case(MEDIA_VISION_COLORSPACE_I420):
640 strncpy(format, "I420", 4);
642 case(MEDIA_VISION_COLORSPACE_NV12):
643 strncpy(format, "NV12", 4);
645 case(MEDIA_VISION_COLORSPACE_YV12):
646 strncpy(format, "YV12", 4);
648 case(MEDIA_VISION_COLORSPACE_NV21):
649 strncpy(format, "NV21", 4);
651 case(MEDIA_VISION_COLORSPACE_YUYV):
652 strncpy(format, "YUY2", 4);
654 case(MEDIA_VISION_COLORSPACE_UYVY):
655 strncpy(format, "UYVY", 4);
657 case(MEDIA_VISION_COLORSPACE_RGB888):
658 strncpy(format, "RGB", 3);
660 case(MEDIA_VISION_COLORSPACE_RGBA):
661 strncpy(format, "RGBA", 4);
664 LOGE("Selected format %d is not supported",
665 writer->image_data.image_colorspace);
666 return MEDIA_VISION_ERROR_NOT_SUPPORTED_FORMAT;
669 caps = gst_caps_new_simple("video/x-raw",
670 "format", G_TYPE_STRING, format,
671 "width", G_TYPE_INT, writer->image_data.image_width,
672 "height", G_TYPE_INT, writer->image_data.image_height,
673 "framerate", GST_TYPE_FRACTION, writer->fps, 1,
677 LOGE("Failed to create new caps");
678 return MEDIA_VISION_ERROR_INVALID_OPERATION;
681 /* This is the simpler way to get buffer size */
682 if (!gst_video_info_from_caps(&vinfo, caps)) {
683 LOGE("Unable to set buffer size");
684 gst_caps_unref(caps);
685 return MEDIA_VISION_ERROR_INVALID_OPERATION;
688 writer->buffer_size = vinfo.size;
690 /* link appsrc and capsfilter */
691 if ((!gst_element_link_filtered(writer->appsrc,
694 LOGE("Failed to link appsrc to capsfilter");
695 gst_caps_unref(caps);
696 return MEDIA_VISION_ERROR_INVALID_OPERATION;
698 gst_caps_unref(caps);
700 if (!gst_element_link_many(writer->capsfilter,
701 writer->videoconvert,
707 LOGE("Unable to capsfilter to filesink");
708 return MEDIA_VISION_ERROR_INVALID_OPERATION;
711 g_object_set(G_OBJECT(writer->appsrc),
713 "blocksize", writer->buffer_size,
715 "format", GST_FORMAT_BYTES,
718 if (_mv_video_writer_state_change(writer,
719 GST_STATE_PLAYING)) {
720 LOGE("Unable to change video writer state");
721 return MEDIA_VISION_ERROR_INVALID_OPERATION;
724 return MEDIA_VISION_ERROR_NONE;
727 static int _mv_video_writer_state_change(
728 mv_video_writer_s *writer,
731 mv_video_writer_s *handle = (mv_video_writer_s *) writer;
732 GstStateChangeReturn state_ret = GST_STATE_CHANGE_FAILURE;
733 GstState pipeline_state = GST_STATE_NULL;
735 state_ret = gst_element_set_state(handle->pl,
738 if (GST_STATE_CHANGE_FAILURE == state_ret) {
739 LOGE("Set state failure");
740 return MEDIA_VISION_ERROR_INVALID_OPERATION;
743 LOGI("Set state [%d], change return [%d]",
746 /* AppSrc can't go to PLAYING state before buffer is not pushed */
748 return MEDIA_VISION_ERROR_NONE;
752 static GstFlowReturn appsink_newsample(
756 mv_video_reader_s *handle = NULL;
757 GstSample *sample = gst_app_sink_pull_sample(appsink);
759 if (user_data == NULL) {
760 LOGE("NULL pointer passed");
761 return MEDIA_VISION_ERROR_INVALID_PARAMETER;
764 if (sample != NULL) {
765 handle = (mv_video_reader_s *) user_data;
767 GstMapInfo info = GST_MAP_INFO_INIT;
768 GstBuffer *buf = gst_sample_get_buffer(sample);
769 GstCaps *caps = gst_sample_get_caps(sample);
770 image_data_s im_data;
772 unsigned int buffer_size = 0;
774 LOGD("Received sample from appsink");
777 gst_buffer_map(buf, &info, GST_MAP_READ);
778 buffer = (char *) info.data;
780 /* Fill image data */
781 gst_video_info_from_caps(&vinfo, caps);
782 im_data.image_width = vinfo.width;
783 im_data.image_height = vinfo.height;
786 * http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-libs/html/gst-plugins-base-libs-gstvideo.html#GstVideoFormat */
787 switch (GST_VIDEO_FORMAT_INFO_FORMAT(vinfo.finfo)) {
788 case(GST_VIDEO_FORMAT_GRAY8):
789 im_data.image_colorspace = MEDIA_VISION_COLORSPACE_Y800;
791 case(GST_VIDEO_FORMAT_I420):
792 im_data.image_colorspace = MEDIA_VISION_COLORSPACE_I420;
794 case(GST_VIDEO_FORMAT_NV12):
795 im_data.image_colorspace = MEDIA_VISION_COLORSPACE_NV12;
797 case(GST_VIDEO_FORMAT_YV12):
798 im_data.image_colorspace = MEDIA_VISION_COLORSPACE_YV12;
800 case(GST_VIDEO_FORMAT_NV21):
801 im_data.image_colorspace = MEDIA_VISION_COLORSPACE_NV21;
803 case(GST_VIDEO_FORMAT_YUY2):
804 im_data.image_colorspace = MEDIA_VISION_COLORSPACE_YUYV;
806 case(GST_VIDEO_FORMAT_UYVY):
807 im_data.image_colorspace = MEDIA_VISION_COLORSPACE_UYVY;
809 case(GST_VIDEO_FORMAT_RGB):
810 im_data.image_colorspace = MEDIA_VISION_COLORSPACE_RGB888;
812 case(GST_VIDEO_FORMAT_RGBA):
813 im_data.image_colorspace = MEDIA_VISION_COLORSPACE_RGBA;
816 LOGE("Video pixel format is not supported\n");
817 gst_buffer_unmap(buf, &info);
818 gst_sample_unref(sample);
819 return GST_FLOW_ERROR;
822 pthread_spin_lock(&(handle->new_sample_cb_guard));
823 if (handle->new_sample_cb != NULL) {
824 handle->new_sample_cb(
828 handle->new_sample_cb_user_data);
830 pthread_spin_unlock(&(handle->new_sample_cb_guard));
832 gst_buffer_unmap(buf, &info);
833 gst_sample_unref(sample);
835 LOGE("Failed to pull sample from appsink");
836 return GST_FLOW_ERROR;
842 static void appsink_eos(
846 if (user_data == NULL) {
847 LOGE("NULL pointer passed");
851 mv_video_reader_s *handle = (mv_video_reader_s *) user_data;
853 /* EOS callback to terminate reading */
854 pthread_spin_lock(&(handle->eos_cb_guard));
855 if (handle->eos_cb != NULL)
856 handle->eos_cb(handle->eos_cb_user_data);
858 pthread_spin_unlock(&(handle->eos_cb_guard));
861 gst_pad_remove_probe(gst_element_get_static_pad(handle->queue, "src"), handle->pad_probe_id);
864 static void cb_newpad(
865 GstElement *decodebin,
869 mv_video_reader_s *reader = (mv_video_reader_s *) user_data;
870 GstStructure *str = NULL;
871 GstCaps *caps = NULL;
872 GstPad *video_pad = NULL;
874 LOGI("Received pad from decodebin. Linking");
875 video_pad = gst_element_get_static_pad(reader->videoconvert, "sink");
876 if (GST_PAD_IS_LINKED(video_pad)) {
877 LOGI("Already linked");
878 g_object_unref(video_pad);
882 /* Check for pad is video */
883 caps = gst_pad_query_caps(pad, NULL);
884 str = gst_caps_get_structure(caps, 0);
885 if (!g_strrstr(gst_structure_get_name(str), "video")) {
886 LOGI("Not a video pad");
887 gst_object_unref(video_pad);
890 gst_caps_unref(caps);
891 gst_pad_link(pad, video_pad);
892 g_object_unref(video_pad);
895 static GstPadProbeReturn pad_probe_data_cb(
897 GstPadProbeInfo *info,
900 if (user_data == NULL)
901 return GST_PAD_PROBE_PASS;
903 mv_video_reader_s *reader = (mv_video_reader_s *) user_data;
905 if (reader->caps == NULL) {
906 reader->caps = gst_pad_get_current_caps(pad);
907 reader->pad_probe_id = GST_PAD_PROBE_INFO_ID(info);
910 return GST_PAD_PROBE_OK;