static void process_video (GstMerger * merger) { GST_DEBUG_OBJECT (merger, "Task function begin"); beg: GST_DEBUG_OBJECT (merger, "Task function loop"); if ((volatile int) merger->stop) { GST_INFO_OBJECT (merger, "Task goto end"); goto end; } g_mutex_trylock (&merger->task_lock); GST_DEBUG_OBJECT (merger, "Task waiting for cond"); g_cond_wait (&merger->task_cond, &merger->task_lock); GST_DEBUG_OBJECT (merger, "Task processing"); while (1) { GstBuffer *buf_l = NULL; GstBuffer *buf_r = NULL; if (GST_PAD_IS_EOS (merger->sinkl_pad)) { goto beg; } if (GST_PAD_IS_EOS (merger->sinkr_pad)) { goto beg; } if (g_queue_is_empty (&merger->bufs_l)) { GST_DEBUG_OBJECT (merger, "No L buffers left"); goto beg; } if (g_queue_is_empty (&merger->bufs_r)) { GST_DEBUG_OBJECT (merger, "No R buffers left"); goto beg; } GST_OBJECT_LOCK (merger); GstBuffer *buf_l0 = g_queue_peek_head (&merger->bufs_l); GstBuffer *buf_l1 = g_queue_peek_tail (&merger->bufs_l); GstBuffer *buf_r0 = g_queue_peek_head (&merger->bufs_r); GstBuffer *buf_r1 = g_queue_peek_tail (&merger->bufs_r); GST_DEBUG_OBJECT (merger, "L0: %" GST_PTR_FORMAT, buf_l0); GST_DEBUG_OBJECT (merger, "L1: %" GST_PTR_FORMAT, buf_l1); GST_DEBUG_OBJECT (merger, "R0: %" GST_PTR_FORMAT, buf_r0); GST_DEBUG_OBJECT (merger, "R1: %" GST_PTR_FORMAT, buf_r1); if (GST_BUFFER_PTS (buf_l0) >= GST_BUFFER_PTS (buf_r0) && GST_BUFFER_PTS (buf_l0) <= GST_BUFFER_PTS (buf_r0) + GST_BUFFER_DURATION (buf_r0)) { buf_l = g_queue_pop_head (&merger->bufs_l); buf_r = g_queue_pop_head (&merger->bufs_r); } else if (GST_BUFFER_PTS (buf_r0) >= GST_BUFFER_PTS (buf_l0) && GST_BUFFER_PTS (buf_r0) <= GST_BUFFER_PTS (buf_l0) + GST_BUFFER_DURATION (buf_l0)) { buf_l = g_queue_pop_head (&merger->bufs_l); buf_r = g_queue_pop_head (&merger->bufs_r); } else if (GST_BUFFER_PTS (buf_r0) + GST_BUFFER_DURATION (buf_r0) < GST_BUFFER_PTS (buf_l0)) { buf_r = g_queue_pop_head (&merger->bufs_r); gst_buffer_unref (buf_r); buf_r = NULL; GST_DEBUG_OBJECT (merger, "Discarding one R"); GST_OBJECT_UNLOCK (merger); continue; } else if (GST_BUFFER_PTS (buf_l0) + GST_BUFFER_DURATION (buf_l0) < GST_BUFFER_PTS (buf_r0)) { buf_l = g_queue_pop_head (&merger->bufs_l); gst_buffer_unref (buf_l); buf_l = NULL; GST_DEBUG_OBJECT (merger, "Discarding one L"); GST_OBJECT_UNLOCK (merger); continue; } else { GST_DEBUG_OBJECT (merger, "Not implemented"); } if (buf_l == NULL || buf_r == NULL) { goto beg; } GST_OBJECT_UNLOCK (merger); GST_DEBUG_OBJECT (merger, "Pushing new buffer"); gint w = 1280; gint h = 480; { GstCaps *caps = gst_pad_get_current_caps (merger->srcv_pad); GstStructure *s = gst_caps_get_structure (caps, 0); gst_structure_get_int (s, "width", &w); gst_structure_get_int (s, "height", &h); gst_caps_unref (caps); } GstBuffer *buf_out = gst_buffer_new_allocate (NULL, w * h * 4, NULL); GstMapInfo map_l; GstMapInfo map_r; GstMapInfo map_out; bool res = gst_buffer_map (buf_out, &map_out, GST_MAP_WRITE); g_assert (res); res = gst_buffer_map (buf_l, &map_l, GST_MAP_READ); g_assert (res); res = gst_buffer_map (buf_r, &map_r, GST_MAP_READ); g_assert (res); guint8 *a_o = (guint8 *) map_out.data; guint8 *a_l = (guint8 *) map_l.data; guint8 *a_r = (guint8 *) map_r.data; for (int y = 0; y < h; y++) { for (int x = 0; x < w / 2; x++) { guint8 r = a_l[3 * (y * w / 2 + x) + 0]; guint8 g = a_l[3 * (y * w / 2 + x) + 1]; guint8 b = a_l[3 * (y * w / 2 + x) + 2]; a_o[4 * (y * w + x) + 0] = r; a_o[4 * (y * w + x) + 1] = g; a_o[4 * (y * w + x) + 2] = b; a_o[4 * (y * w + x) + 3] = 255; } for (int x = 0; x < w / 2; x++) { guint8 r = a_r[3 * (y * w / 2 + x) + 0]; guint8 g = a_r[3 * (y * w / 2 + x) + 1]; guint8 b = a_r[3 * (y * w / 2 + x) + 2]; a_o[4 * (y * w + x + w / 2) + 0] = r; a_o[4 * (y * w + x + w / 2) + 1] = g; a_o[4 * (y * w + x + w / 2) + 2] = b; a_o[4 * (y * w + x + w / 2) + 3] = 255; } } usleep (10000); gst_buffer_unmap (buf_l, &map_l); gst_buffer_unmap (buf_r, &map_r); gst_buffer_unmap (buf_out, &map_out); GST_BUFFER_PTS (buf_out) = GST_BUFFER_PTS (buf_l); GST_BUFFER_DTS (buf_out) = GST_BUFFER_DTS (buf_l); GST_BUFFER_DURATION (buf_out) = GST_BUFFER_DURATION (buf_l); gst_buffer_unref (buf_l); gst_buffer_unref (buf_r); int res2 = gst_pad_push (merger->srcv_pad, buf_out); if (res2 != GST_FLOW_OK) { GST_WARNING_OBJECT (merger, "Pushing pad returned %d", res2); goto error; } } goto beg; error: end: GST_INFO_OBJECT (merger, "Task bye bye?"); //gst_task_pause (merger->task); GST_INFO_OBJECT (merger, "Task bye bye"); g_mutex_unlock (&merger->task_lock); }
static void _audiodecoder_flush_events (gboolean send_buffers) { GstSegment segment; GstBuffer *buffer; guint64 i; GList *events_iter; GstMessage *msg; setup_audiodecodertester (); gst_pad_set_active (mysrcpad, TRUE); gst_element_set_state (dec, GST_STATE_PLAYING); gst_pad_set_active (mysinkpad, TRUE); send_startup_events (); /* push a new segment */ gst_segment_init (&segment, GST_FORMAT_TIME); fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment))); if (send_buffers) { /* push buffers, the data is actually a number so we can track them */ for (i = 0; i < NUM_BUFFERS; i++) { if (i % 10 == 0) { GstTagList *tags; tags = gst_tag_list_new (GST_TAG_TRACK_NUMBER, i, NULL); fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_tag (tags))); } else { buffer = create_test_buffer (i); fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); } } } else { /* push sticky event */ GstTagList *tags; tags = gst_tag_list_new (GST_TAG_TRACK_NUMBER, 0, NULL); fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_tag (tags))); } msg = gst_message_new_element (GST_OBJECT (mysrcpad), gst_structure_new_empty ("test")); fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_sink_message ("test", msg))); gst_message_unref (msg); fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ())); events_iter = events; /* make sure the usual events have been received */ { GstEvent *sstart = events_iter->data; fail_unless (GST_EVENT_TYPE (sstart) == GST_EVENT_STREAM_START); events_iter = g_list_next (events_iter); } if (send_buffers) { { GstEvent *caps_event = events_iter->data; fail_unless (GST_EVENT_TYPE (caps_event) == GST_EVENT_CAPS); events_iter = g_list_next (events_iter); } { GstEvent *segment_event = events_iter->data; fail_unless (GST_EVENT_TYPE (segment_event) == GST_EVENT_SEGMENT); events_iter = g_list_next (events_iter); } for (int i=0; i< NUM_BUFFERS / 10; i++) { GstEvent *tag_event = events_iter->data; fail_unless (GST_EVENT_TYPE (tag_event) == GST_EVENT_TAG); events_iter = g_list_next (events_iter); } } { GstEvent *eos_event = events_iter->data; fail_unless (GST_EVENT_TYPE (eos_event) == GST_EVENT_EOS); events_iter = g_list_next (events_iter); } /* check that EOS was received */ fail_unless (GST_PAD_IS_EOS (mysrcpad)); fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_flush_start ())); fail_unless (GST_PAD_IS_EOS (mysrcpad)); /* Check that we have tags */ { GstEvent *tags = gst_pad_get_sticky_event (mysrcpad, GST_EVENT_TAG, 0); fail_unless (tags != NULL); gst_event_unref (tags); } /* Check that we still have a segment set */ { GstEvent *segment = gst_pad_get_sticky_event (mysrcpad, GST_EVENT_SEGMENT, 0); fail_unless (segment != NULL); gst_event_unref (segment); } fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_flush_stop (TRUE))); fail_if (GST_PAD_IS_EOS (mysrcpad)); /* Check that the segment was flushed on FLUSH_STOP */ { GstEvent *segment = gst_pad_get_sticky_event (mysrcpad, GST_EVENT_SEGMENT, 0); fail_unless (segment == NULL); } /* Check the tags were not lost on FLUSH_STOP */ { GstEvent *tags = gst_pad_get_sticky_event (mysrcpad, GST_EVENT_TAG, 0); fail_unless (tags != NULL); gst_event_unref (tags); } g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref); buffers = NULL; gst_element_set_state (dec, GST_STATE_NULL); cleanup_audiodecodertest (); }