static gboolean gst_video_test_src_do_seek (GstBaseSrc * bsrc, GstSegment * segment) { GstClockTime time; GstVideoTestSrc *src; src = GST_VIDEO_TEST_SRC (bsrc); segment->time = segment->start; time = segment->last_stop; /* now move to the time indicated */ if (src->rate_numerator) { src->n_frames = gst_util_uint64_scale (time, src->rate_numerator, src->rate_denominator * GST_SECOND); } else { src->n_frames = 0; } if (src->rate_numerator) { src->running_time = gst_util_uint64_scale (src->n_frames, src->rate_denominator * GST_SECOND, src->rate_numerator); } else { /* FIXME : Not sure what to set here */ src->running_time = 0; } g_assert (src->running_time <= time); return TRUE; }
static gboolean gst_video_test_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps) { gboolean res; gint width, height, rate_denominator, rate_numerator; struct fourcc_list_struct *fourcc; GstVideoTestSrc *videotestsrc; videotestsrc = GST_VIDEO_TEST_SRC (bsrc); res = gst_video_test_src_parse_caps (caps, &width, &height, &rate_numerator, &rate_denominator, &fourcc); if (res) { /* looks ok here */ videotestsrc->fourcc = fourcc; videotestsrc->width = width; videotestsrc->height = height; videotestsrc->rate_numerator = rate_numerator; videotestsrc->rate_denominator = rate_denominator; videotestsrc->bpp = videotestsrc->fourcc->bitspp; GST_DEBUG_OBJECT (videotestsrc, "size %dx%d, %d/%d fps", videotestsrc->width, videotestsrc->height, videotestsrc->rate_numerator, videotestsrc->rate_denominator); } return res; }
static gboolean gst_video_test_src_do_seek (GstBaseSrc * bsrc, GstSegment * segment) { GstClockTime position; GstVideoTestSrc *src; src = GST_VIDEO_TEST_SRC (bsrc); segment->time = segment->start; position = segment->position; /* now move to the position indicated */ if (src->info.fps_n) { src->n_frames = gst_util_uint64_scale (position, src->info.fps_n, src->info.fps_d * GST_SECOND); } else { src->n_frames = 0; } src->accum_frames = 0; src->accum_rtime = 0; if (src->info.fps_n) { src->running_time = gst_util_uint64_scale (src->n_frames, src->info.fps_d * GST_SECOND, src->info.fps_n); } else { /* FIXME : Not sure what to set here */ src->running_time = 0; } g_assert (src->running_time <= position); return TRUE; }
static gboolean gst_video_test_src_query (GstBaseSrc * bsrc, GstQuery * query) { gboolean res; GstVideoTestSrc *src; src = GST_VIDEO_TEST_SRC (bsrc); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_CONVERT: { GstFormat src_fmt, dest_fmt; gint64 src_val, dest_val; gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); res = gst_video_info_convert (&src->info, src_fmt, src_val, dest_fmt, &dest_val); gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); break; } default: res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query); break; } return res; }
static gboolean gst_video_test_src_start (GstBaseSrc * basesrc) { GstVideoTestSrc *src = GST_VIDEO_TEST_SRC (basesrc); src->running_time = 0; src->n_frames = 0; return TRUE; }
static gboolean gst_video_test_src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query) { GstVideoTestSrc *videotestsrc; GstBufferPool *pool; gboolean update; guint size, min, max; GstStructure *config; videotestsrc = GST_VIDEO_TEST_SRC (bsrc); if (gst_query_get_n_allocation_pools (query) > 0) { gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); /* adjust size */ size = MAX (size, videotestsrc->info.size); update = TRUE; } else { pool = NULL; size = videotestsrc->info.size; min = max = 0; update = FALSE; } /* no downstream pool, make our own */ if (pool == NULL) { if (videotestsrc->bayer) pool = gst_buffer_pool_new (); else pool = gst_video_buffer_pool_new (); } config = gst_buffer_pool_get_config (pool); if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL)) { gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); } gst_buffer_pool_set_config (pool, config); if (update) gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max); else gst_query_add_allocation_pool (query, pool, size, min, max); if (pool) gst_object_unref (pool); return GST_BASE_SRC_CLASS (parent_class)->decide_allocation (bsrc, query); }
static gboolean gst_video_test_src_stop (GstBaseSrc * basesrc) { GstVideoTestSrc *src = GST_VIDEO_TEST_SRC (basesrc); g_free (src->tmpline); src->tmpline = NULL; g_free (src->tmpline2); src->tmpline2 = NULL; g_free (src->tmpline_u8); src->tmpline_u8 = NULL; g_free (src->tmpline_u16); src->tmpline_u16 = NULL; return TRUE; }
static void gst_video_test_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstVideoTestSrc *src = GST_VIDEO_TEST_SRC (object); switch (prop_id) { case PROP_PATTERN: gst_video_test_src_set_pattern (src, g_value_get_enum (value)); break; case PROP_TIMESTAMP_OFFSET: src->timestamp_offset = g_value_get_int64 (value); break; case PROP_IS_LIVE: gst_base_src_set_live (GST_BASE_SRC (src), g_value_get_boolean (value)); break; default: break; } }
static void gst_video_test_src_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstVideoTestSrc *src = GST_VIDEO_TEST_SRC (object); switch (prop_id) { case PROP_PATTERN: g_value_set_enum (value, src->pattern_type); break; case PROP_TIMESTAMP_OFFSET: g_value_set_int64 (value, src->timestamp_offset); break; case PROP_IS_LIVE: g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (src))); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static GstFlowReturn gst_video_test_src_create (GstPushSrc * psrc, GstBuffer ** buffer) { GstVideoTestSrc *src; gulong newsize; GstBuffer *outbuf; GstFlowReturn res; GstClockTime next_time; src = GST_VIDEO_TEST_SRC (psrc); if (G_UNLIKELY (src->fourcc == NULL)) goto not_negotiated; /* 0 framerate and we are at the second frame, eos */ if (G_UNLIKELY (src->rate_numerator == 0 && src->n_frames == 1)) goto eos; newsize = gst_video_test_src_get_size (src, src->width, src->height); g_return_val_if_fail (newsize > 0, GST_FLOW_ERROR); GST_LOG_OBJECT (src, "creating buffer of %lu bytes with %dx%d image for frame %d", newsize, src->width, src->height, (gint) src->n_frames); #ifdef USE_PEER_BUFFERALLOC res = gst_pad_alloc_buffer_and_set_caps (GST_BASE_SRC_PAD (psrc), GST_BUFFER_OFFSET_NONE, newsize, GST_PAD_CAPS (GST_BASE_SRC_PAD (psrc)), &outbuf); if (res != GST_FLOW_OK) goto no_buffer; #else outbuf = gst_buffer_new_and_alloc (newsize); gst_buffer_set_caps (outbuf, GST_PAD_CAPS (GST_BASE_SRC_PAD (psrc))); #endif if (src->pattern_type == GST_VIDEO_TEST_SRC_BLINK) { if (src->n_frames & 0x1) { gst_video_test_src_white (src, (void *) GST_BUFFER_DATA (outbuf), src->width, src->height); } else { gst_video_test_src_black (src, (void *) GST_BUFFER_DATA (outbuf), src->width, src->height); } } else { src->make_image (src, (void *) GST_BUFFER_DATA (outbuf), src->width, src->height); } GST_BUFFER_TIMESTAMP (outbuf) = src->timestamp_offset + src->running_time; GST_BUFFER_OFFSET (outbuf) = src->n_frames; src->n_frames++; GST_BUFFER_OFFSET_END (outbuf) = src->n_frames; if (src->rate_numerator) { next_time = gst_util_uint64_scale_int (src->n_frames * GST_SECOND, src->rate_denominator, src->rate_numerator); GST_BUFFER_DURATION (outbuf) = next_time - src->running_time; } else { next_time = src->timestamp_offset; /* NONE means forever */ GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE; } src->running_time = next_time; *buffer = outbuf; return GST_FLOW_OK; not_negotiated: { GST_ELEMENT_ERROR (src, CORE, NEGOTIATION, (NULL), ("format wasn't negotiated before get function")); return GST_FLOW_NOT_NEGOTIATED; } eos: { GST_DEBUG_OBJECT (src, "eos: 0 framerate, frame %d", (gint) src->n_frames); return GST_FLOW_UNEXPECTED; } no_buffer: { GST_DEBUG_OBJECT (src, "could not allocate buffer, reason %s", gst_flow_get_name (res)); return res; } }
static gboolean gst_video_test_src_query (GstBaseSrc * bsrc, GstQuery * query) { gboolean res; GstVideoTestSrc *src; src = GST_VIDEO_TEST_SRC (bsrc); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_CONVERT: { GstFormat src_fmt, dest_fmt; gint64 src_val, dest_val; gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); if (src_fmt == dest_fmt) { dest_val = src_val; goto done; } switch (src_fmt) { case GST_FORMAT_DEFAULT: switch (dest_fmt) { case GST_FORMAT_TIME: /* frames to time */ if (src->rate_numerator) { dest_val = gst_util_uint64_scale (src_val, src->rate_denominator * GST_SECOND, src->rate_numerator); } else { dest_val = 0; } break; default: goto error; } break; case GST_FORMAT_TIME: switch (dest_fmt) { case GST_FORMAT_DEFAULT: /* time to frames */ if (src->rate_numerator) { dest_val = gst_util_uint64_scale (src_val, src->rate_numerator, src->rate_denominator * GST_SECOND); } else { dest_val = 0; } break; default: goto error; } break; default: goto error; } done: gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); res = TRUE; break; } default: res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query); } return res; /* ERROR */ error: { GST_DEBUG_OBJECT (src, "query failed"); return FALSE; } }
static void gst_video_test_src_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstVideoTestSrc *src = GST_VIDEO_TEST_SRC (object); switch (prop_id) { case PROP_PATTERN: g_value_set_enum (value, src->pattern_type); break; case PROP_TIMESTAMP_OFFSET: g_value_set_int64 (value, src->timestamp_offset); break; case PROP_IS_LIVE: g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (src))); break; case PROP_PEER_ALLOC: g_value_set_boolean (value, src->peer_alloc); break; case PROP_COLOR_SPEC: g_value_set_enum (value, src->color_spec); break; case PROP_K0: g_value_set_int (value, src->k0); break; case PROP_KX: g_value_set_int (value, src->kx); break; case PROP_KY: g_value_set_int (value, src->ky); break; case PROP_KT: g_value_set_int (value, src->kt); break; case PROP_KXT: g_value_set_int (value, src->kxt); break; case PROP_KYT: g_value_set_int (value, src->kyt); break; case PROP_KXY: g_value_set_int (value, src->kxy); break; case PROP_KX2: g_value_set_int (value, src->kx2); break; case PROP_KY2: g_value_set_int (value, src->ky2); break; case PROP_KT2: g_value_set_int (value, src->kt2); break; case PROP_XOFFSET: g_value_set_int (value, src->xoffset); break; case PROP_YOFFSET: g_value_set_int (value, src->yoffset); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void gst_video_test_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstVideoTestSrc *src = GST_VIDEO_TEST_SRC (object); switch (prop_id) { case PROP_PATTERN: gst_video_test_src_set_pattern (src, g_value_get_enum (value)); break; case PROP_TIMESTAMP_OFFSET: src->timestamp_offset = g_value_get_int64 (value); break; case PROP_IS_LIVE: gst_base_src_set_live (GST_BASE_SRC (src), g_value_get_boolean (value)); break; case PROP_PEER_ALLOC: src->peer_alloc = g_value_get_boolean (value); break; case PROP_COLOR_SPEC: src->color_spec = g_value_get_enum (value); break; case PROP_K0: src->k0 = g_value_get_int (value); break; case PROP_KX: src->kx = g_value_get_int (value); break; case PROP_KY: src->ky = g_value_get_int (value); break; case PROP_KT: src->kt = g_value_get_int (value); break; case PROP_KXT: src->kxt = g_value_get_int (value); break; case PROP_KYT: src->kyt = g_value_get_int (value); break; case PROP_KXY: src->kxy = g_value_get_int (value); break; case PROP_KX2: src->kx2 = g_value_get_int (value); break; case PROP_KY2: src->ky2 = g_value_get_int (value); break; case PROP_KT2: src->kt2 = g_value_get_int (value); break; case PROP_XOFFSET: src->xoffset = g_value_get_int (value); break; case PROP_YOFFSET: src->yoffset = g_value_get_int (value); break; default: break; } }
static GstFlowReturn gst_video_test_src_fill (GstPushSrc * psrc, GstBuffer * buffer) { GstVideoTestSrc *src; GstClockTime next_time; GstVideoFrame frame; gconstpointer pal; gsize palsize; src = GST_VIDEO_TEST_SRC (psrc); if (G_UNLIKELY (GST_VIDEO_INFO_FORMAT (&src->info) == GST_VIDEO_FORMAT_UNKNOWN)) goto not_negotiated; /* 0 framerate and we are at the second frame, eos */ if (G_UNLIKELY (src->info.fps_n == 0 && src->n_frames == 1)) goto eos; GST_LOG_OBJECT (src, "creating buffer from pool for frame %d", (gint) src->n_frames); if (!gst_video_frame_map (&frame, &src->info, buffer, GST_MAP_WRITE)) goto invalid_frame; src->make_image (src, &frame); if ((pal = gst_video_format_get_palette (GST_VIDEO_FRAME_FORMAT (&frame), &palsize))) { memcpy (GST_VIDEO_FRAME_PLANE_DATA (&frame, 1), pal, palsize); } gst_video_frame_unmap (&frame); GST_BUFFER_DTS (buffer) = src->accum_rtime + src->timestamp_offset + src->running_time; GST_BUFFER_PTS (buffer) = GST_BUFFER_DTS (buffer); GST_DEBUG_OBJECT (src, "Timestamp: %" GST_TIME_FORMAT " = accumulated %" GST_TIME_FORMAT " + offset: %" GST_TIME_FORMAT " + running time: %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (buffer)), GST_TIME_ARGS (src->accum_rtime), GST_TIME_ARGS (src->timestamp_offset), GST_TIME_ARGS (src->running_time)); GST_BUFFER_OFFSET (buffer) = src->accum_frames + src->n_frames; src->n_frames++; GST_BUFFER_OFFSET_END (buffer) = GST_BUFFER_OFFSET (buffer) + 1; if (src->info.fps_n) { next_time = gst_util_uint64_scale_int (src->n_frames * GST_SECOND, src->info.fps_d, src->info.fps_n); GST_BUFFER_DURATION (buffer) = next_time - src->running_time; } else { next_time = src->timestamp_offset; /* NONE means forever */ GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE; } src->running_time = next_time; return GST_FLOW_OK; not_negotiated: { GST_ELEMENT_ERROR (src, CORE, NEGOTIATION, (NULL), ("format wasn't negotiated before get function")); return GST_FLOW_NOT_NEGOTIATED; } eos: { GST_DEBUG_OBJECT (src, "eos: 0 framerate, frame %d", (gint) src->n_frames); return GST_FLOW_EOS; } invalid_frame: { GST_DEBUG_OBJECT (src, "invalid frame"); return GST_FLOW_OK; } }
static gboolean gst_video_test_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps) { const GstStructure *structure; GstVideoTestSrc *videotestsrc; GstVideoInfo info; videotestsrc = GST_VIDEO_TEST_SRC (bsrc); structure = gst_caps_get_structure (caps, 0); if (gst_structure_has_name (structure, "video/x-raw")) { /* we can use the parsing code */ if (!gst_video_info_from_caps (&info, caps)) goto parse_failed; } else if (gst_structure_has_name (structure, "video/x-bayer")) { gint x_inv = 0, y_inv = 0; gst_video_info_init (&info); info.finfo = gst_video_format_get_info (GST_VIDEO_FORMAT_GRAY8); if (!gst_video_test_src_parse_caps (caps, &info.width, &info.height, &info.fps_n, &info.fps_d, &info.colorimetry, &x_inv, &y_inv)) goto parse_failed; info.size = GST_ROUND_UP_4 (info.width) * info.height; info.stride[0] = GST_ROUND_UP_4 (info.width); videotestsrc->bayer = TRUE; videotestsrc->x_invert = x_inv; videotestsrc->y_invert = y_inv; } /* looks ok here */ videotestsrc->info = info; GST_DEBUG_OBJECT (videotestsrc, "size %dx%d, %d/%d fps", info.width, info.height, info.fps_n, info.fps_d); g_free (videotestsrc->tmpline); g_free (videotestsrc->tmpline2); g_free (videotestsrc->tmpline_u8); g_free (videotestsrc->tmpline_u16); videotestsrc->tmpline_u8 = g_malloc (info.width + 8); videotestsrc->tmpline = g_malloc ((info.width + 8) * 4); videotestsrc->tmpline2 = g_malloc ((info.width + 8) * 4); videotestsrc->tmpline_u16 = g_malloc ((info.width + 16) * 8); videotestsrc->accum_rtime += videotestsrc->running_time; videotestsrc->accum_frames += videotestsrc->n_frames; videotestsrc->running_time = 0; videotestsrc->n_frames = 0; return TRUE; /* ERRORS */ parse_failed: { GST_DEBUG_OBJECT (bsrc, "failed to parse caps"); return FALSE; } }
static void gst_video_test_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstVideoTestSrc *src = GST_VIDEO_TEST_SRC (object); switch (prop_id) { case PROP_PATTERN: gst_video_test_src_set_pattern (src, g_value_get_enum (value)); break; case PROP_TIMESTAMP_OFFSET: src->timestamp_offset = g_value_get_int64 (value); break; case PROP_IS_LIVE: gst_base_src_set_live (GST_BASE_SRC (src), g_value_get_boolean (value)); break; case PROP_K0: src->k0 = g_value_get_int (value); break; case PROP_KX: src->kx = g_value_get_int (value); break; case PROP_KY: src->ky = g_value_get_int (value); break; case PROP_KT: src->kt = g_value_get_int (value); break; case PROP_KXT: src->kxt = g_value_get_int (value); break; case PROP_KYT: src->kyt = g_value_get_int (value); break; case PROP_KXY: src->kxy = g_value_get_int (value); break; case PROP_KX2: src->kx2 = g_value_get_int (value); break; case PROP_KY2: src->ky2 = g_value_get_int (value); break; case PROP_KT2: src->kt2 = g_value_get_int (value); break; case PROP_XOFFSET: src->xoffset = g_value_get_int (value); break; case PROP_YOFFSET: src->yoffset = g_value_get_int (value); break; case PROP_FOREGROUND_COLOR: src->foreground_color = g_value_get_uint (value); break; case PROP_BACKGROUND_COLOR: src->background_color = g_value_get_uint (value); break; case PROP_HORIZONTAL_SPEED: src->horizontal_speed = g_value_get_int (value); default: break; } }