static gboolean gst_base_video_decoder_sink_activate (GstBaseVideoDecoder * decoder, gboolean active) { GstBaseVideoDecoderClass *klass; gboolean result = FALSE; GST_DEBUG_OBJECT (decoder, "activate"); klass = GST_BASE_VIDEO_DECODER_GET_CLASS (decoder); if (active) { if (klass->start) result = klass->start (decoder); } else { /* We must make sure streaming has finished before resetting things * and calling the ::stop vfunc */ GST_PAD_STREAM_LOCK (GST_BASE_VIDEO_CODEC_SINK_PAD (decoder)); GST_PAD_STREAM_UNLOCK (GST_BASE_VIDEO_CODEC_SINK_PAD (decoder)); if (klass->stop) result = klass->stop (decoder); } GST_DEBUG_OBJECT (decoder, "activate: %d", result); return result; }
static void gst_base_video_decoder_init (GstBaseVideoDecoder * base_video_decoder, GstBaseVideoDecoderClass * klass) { GstPad *pad; GST_DEBUG ("gst_base_video_decoder_init"); pad = GST_BASE_VIDEO_CODEC_SINK_PAD (base_video_decoder); gst_pad_set_activatepush_function (pad, gst_base_video_decoder_sink_activate_push); gst_pad_set_chain_function (pad, gst_base_video_decoder_chain); gst_pad_set_event_function (pad, gst_base_video_decoder_sink_event); gst_pad_set_setcaps_function (pad, gst_base_video_decoder_sink_setcaps); gst_pad_set_query_function (pad, gst_base_video_decoder_sink_query); pad = GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_decoder); gst_pad_set_event_function (pad, gst_base_video_decoder_src_event); gst_pad_set_query_type_function (pad, gst_base_video_decoder_get_query_types); gst_pad_set_query_function (pad, gst_base_video_decoder_src_query); base_video_decoder->input_adapter = gst_adapter_new (); base_video_decoder->output_adapter = gst_adapter_new (); gst_segment_init (&base_video_decoder->state.segment, GST_FORMAT_TIME); gst_base_video_decoder_reset (base_video_decoder); base_video_decoder->current_frame = gst_base_video_decoder_new_frame (base_video_decoder); base_video_decoder->sink_clipping = TRUE; }
static void gst_base_video_parse_init (GstBaseVideoParse * base_video_parse, GstBaseVideoParseClass * klass) { GstPad *pad; GST_DEBUG ("gst_base_video_parse_init"); pad = GST_BASE_VIDEO_CODEC_SINK_PAD (base_video_parse); gst_pad_set_chain_function (pad, gst_base_video_parse_chain); gst_pad_set_query_function (pad, gst_base_video_parse_sink_query); gst_pad_set_event_function (pad, gst_base_video_parse_sink_event); pad = GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_parse); gst_pad_set_query_type_function (pad, gst_base_video_parse_get_query_types); gst_pad_set_query_function (pad, gst_base_video_parse_src_query); gst_pad_set_event_function (pad, gst_base_video_parse_src_event); base_video_parse->input_adapter = gst_adapter_new (); base_video_parse->output_adapter = gst_adapter_new (); base_video_parse->reorder_depth = 1; base_video_parse->current_frame = gst_base_video_parse_new_frame (base_video_parse); }
static void gst_base_video_encoder_init (GstBaseVideoEncoder * base_video_encoder, GstBaseVideoEncoderClass * klass) { GstPad *pad; GST_DEBUG_OBJECT (base_video_encoder, "gst_base_video_encoder_init"); pad = GST_BASE_VIDEO_CODEC_SINK_PAD (base_video_encoder); gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_base_video_encoder_chain)); gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_base_video_encoder_sink_event)); gst_pad_set_setcaps_function (pad, GST_DEBUG_FUNCPTR (gst_base_video_encoder_sink_setcaps)); gst_pad_set_getcaps_function (pad, GST_DEBUG_FUNCPTR (gst_base_video_encoder_sink_getcaps)); pad = GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder); gst_pad_set_query_type_function (pad, GST_DEBUG_FUNCPTR (gst_base_video_encoder_get_query_types)); gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_base_video_encoder_src_query)); gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_base_video_encoder_src_event)); base_video_encoder->a.at_eos = FALSE; /* encoder is expected to do so */ base_video_encoder->sink_clipping = TRUE; }
static gboolean gst_base_video_encoder_src_query (GstPad * pad, GstQuery * query) { GstBaseVideoEncoder *enc; gboolean res; GstPad *peerpad; enc = GST_BASE_VIDEO_ENCODER (gst_pad_get_parent (pad)); peerpad = gst_pad_get_peer (GST_BASE_VIDEO_CODEC_SINK_PAD (enc)); 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_base_video_encoded_video_convert (&GST_BASE_VIDEO_CODEC (enc)->state, src_fmt, src_val, &dest_fmt, &dest_val); if (!res) goto error; gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); break; } case GST_QUERY_LATENCY: { gboolean live; GstClockTime min_latency, max_latency; res = gst_pad_query (peerpad, query); if (res) { gst_query_parse_latency (query, &live, &min_latency, &max_latency); min_latency += enc->min_latency; if (max_latency != GST_CLOCK_TIME_NONE) { max_latency += enc->max_latency; } gst_query_set_latency (query, live, min_latency, max_latency); } } break; default: res = gst_pad_query_default (pad, query); } gst_object_unref (peerpad); gst_object_unref (enc); return res; error: GST_DEBUG_OBJECT (enc, "query failed"); gst_object_unref (peerpad); gst_object_unref (enc); return res; }
static gboolean gst_base_video_encoder_src_event (GstPad * pad, GstEvent * event) { GstBaseVideoEncoder *base_video_encoder; GstBaseVideoEncoderClass *base_video_encoder_class; gboolean ret = FALSE; base_video_encoder = GST_BASE_VIDEO_ENCODER (gst_pad_get_parent (pad)); base_video_encoder_class = GST_BASE_VIDEO_ENCODER_GET_CLASS (base_video_encoder); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_CUSTOM_UPSTREAM: { const GstStructure *s; s = gst_event_get_structure (event); if (gst_structure_has_name (s, "GstForceKeyUnit")) { GST_OBJECT_LOCK (base_video_encoder); base_video_encoder->force_keyframe = TRUE; GST_OBJECT_UNLOCK (base_video_encoder); gst_event_unref (event); ret = TRUE; } else { ret = gst_pad_push_event (GST_BASE_VIDEO_CODEC_SINK_PAD (base_video_encoder), event); } break; } default: ret = gst_pad_push_event (GST_BASE_VIDEO_CODEC_SINK_PAD (base_video_encoder), event); break; } gst_object_unref (base_video_encoder); return ret; }
static void gst_vp8_enc_init (GstVP8Enc * gst_vp8_enc, GstVP8EncClass * klass) { GST_DEBUG_OBJECT (gst_vp8_enc, "init"); gst_vp8_enc->bitrate = DEFAULT_BITRATE; gst_vp8_enc->mode = DEFAULT_MODE; gst_vp8_enc->quality = DEFAULT_QUALITY; gst_vp8_enc->error_resilient = DEFAULT_ERROR_RESILIENT; gst_vp8_enc->max_latency = DEFAULT_MAX_LATENCY; gst_vp8_enc->max_keyframe_distance = DEFAULT_MAX_KEYFRAME_DISTANCE; gst_vp8_enc->multipass_mode = DEFAULT_MULTIPASS_MODE; gst_vp8_enc->multipass_cache_file = DEFAULT_MULTIPASS_CACHE_FILE; gst_vp8_enc->auto_alt_ref_frames = DEFAULT_AUTO_ALT_REF_FRAMES; /* FIXME: Add sink/src event vmethods */ gst_vp8_enc->base_sink_event_func = GST_PAD_EVENTFUNC (GST_BASE_VIDEO_CODEC_SINK_PAD (gst_vp8_enc)); gst_pad_set_event_function (GST_BASE_VIDEO_CODEC_SINK_PAD (gst_vp8_enc), gst_vp8_enc_sink_event); }
static void gst_base_video_encoder_init (GstBaseVideoEncoder * base_video_encoder, GstBaseVideoEncoderClass * klass) { GstPad *pad; GST_DEBUG ("gst_base_video_encoder_init"); pad = GST_BASE_VIDEO_CODEC_SINK_PAD (base_video_encoder); gst_pad_set_chain_function (pad, gst_base_video_encoder_chain); gst_pad_set_event_function (pad, gst_base_video_encoder_sink_event); gst_pad_set_setcaps_function (pad, gst_base_video_encoder_sink_setcaps); //gst_pad_set_query_function (pad, gst_base_video_encoder_sink_query); pad = GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder); gst_pad_set_query_type_function (pad, gst_base_video_encoder_get_query_types); gst_pad_set_query_function (pad, gst_base_video_encoder_src_query); }
static gboolean gst_base_video_decoder_src_event (GstPad * pad, GstEvent * event) { GstBaseVideoDecoder *base_video_decoder; gboolean res = FALSE; base_video_decoder = GST_BASE_VIDEO_DECODER (gst_pad_get_parent (pad)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEEK: { GstFormat format, tformat; gdouble rate; GstEvent *real_seek; GstSeekFlags flags; GstSeekType cur_type, stop_type; gint64 cur, stop; gint64 tcur, tstop; gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur, &stop_type, &stop); gst_event_unref (event); tformat = GST_FORMAT_TIME; res = gst_base_video_decoder_src_convert (pad, format, cur, &tformat, &tcur); if (!res) goto convert_error; res = gst_base_video_decoder_src_convert (pad, format, stop, &tformat, &tstop); if (!res) goto convert_error; real_seek = gst_event_new_seek (rate, GST_FORMAT_TIME, flags, cur_type, tcur, stop_type, tstop); res = gst_pad_push_event (GST_BASE_VIDEO_CODEC_SINK_PAD (base_video_decoder), real_seek); break; } case GST_EVENT_QOS: { gdouble proportion; GstClockTimeDiff diff; GstClockTime timestamp; gst_event_parse_qos (event, &proportion, &diff, ×tamp); GST_OBJECT_LOCK (base_video_decoder); base_video_decoder->proportion = proportion; base_video_decoder->earliest_time = timestamp + diff; GST_OBJECT_UNLOCK (base_video_decoder); GST_DEBUG_OBJECT (base_video_decoder, "got QoS %" GST_TIME_FORMAT ", %" G_GINT64_FORMAT ", %g", GST_TIME_ARGS (timestamp), diff, proportion); res = gst_pad_push_event (GST_BASE_VIDEO_CODEC_SINK_PAD (base_video_decoder), event); break; } default: res = gst_pad_push_event (GST_BASE_VIDEO_CODEC_SINK_PAD (base_video_decoder), event); break; } done: gst_object_unref (base_video_decoder); return res; convert_error: GST_DEBUG_OBJECT (base_video_decoder, "could not convert format"); goto done; }
static gboolean gst_base_video_parse_src_query (GstPad * pad, GstQuery * query) { GstBaseVideoParse *base_parse; gboolean res = FALSE; base_parse = GST_BASE_VIDEO_PARSE (gst_pad_get_parent (pad)); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: { GstFormat format; gint64 time; gint64 value; gst_query_parse_position (query, &format, NULL); time = gst_util_uint64_scale (base_parse->presentation_frame_number, base_parse->state.fps_n, base_parse->state.fps_d); time += base_parse->segment.time; GST_DEBUG ("query position %" GST_TIME_FORMAT, GST_TIME_ARGS (time)); res = gst_base_video_encoded_video_convert (&base_parse->state, GST_FORMAT_TIME, time, &format, &value); if (!res) goto error; gst_query_set_position (query, format, value); break; } case GST_QUERY_DURATION: res = gst_pad_query (GST_PAD_PEER (GST_BASE_VIDEO_CODEC_SINK_PAD (base_parse)), query); if (!res) goto error; break; case GST_QUERY_CONVERT: { GstFormat src_fmt, dest_fmt; gint64 src_val, dest_val; GST_WARNING ("query convert"); gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); res = gst_base_video_encoded_video_convert (&base_parse->state, src_fmt, src_val, &dest_fmt, &dest_val); if (!res) goto error; gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); break; } default: res = gst_pad_query_default (pad, query); break; } done: gst_object_unref (base_parse); return res; error: GST_DEBUG_OBJECT (base_parse, "query failed"); goto done; }
static GstCaps * gst_base_video_encoder_sink_getcaps (GstPad * pad) { GstBaseVideoEncoder *base_video_encoder; const GstCaps *templ_caps; GstCaps *allowed; GstCaps *fcaps, *filter_caps; gint i, j; base_video_encoder = GST_BASE_VIDEO_ENCODER (gst_pad_get_parent (pad)); /* FIXME: Allow subclass to override this? */ /* Allow downstream to specify width/height/framerate/PAR constraints * and forward them upstream for video converters to handle */ templ_caps = gst_pad_get_pad_template_caps (GST_BASE_VIDEO_CODEC_SINK_PAD (base_video_encoder)); allowed = gst_pad_get_allowed_caps (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder)); if (!allowed || gst_caps_is_empty (allowed) || gst_caps_is_any (allowed)) { fcaps = gst_caps_copy (templ_caps); goto done; } GST_LOG_OBJECT (base_video_encoder, "template caps %" GST_PTR_FORMAT, templ_caps); GST_LOG_OBJECT (base_video_encoder, "allowed caps %" GST_PTR_FORMAT, allowed); filter_caps = gst_caps_new_empty (); for (i = 0; i < gst_caps_get_size (templ_caps); i++) { GQuark q_name = gst_structure_get_name_id (gst_caps_get_structure (templ_caps, i)); for (j = 0; j < gst_caps_get_size (allowed); j++) { const GstStructure *allowed_s = gst_caps_get_structure (allowed, j); const GValue *val; GstStructure *s; s = gst_structure_id_empty_new (q_name); if ((val = gst_structure_get_value (allowed_s, "width"))) gst_structure_set_value (s, "width", val); if ((val = gst_structure_get_value (allowed_s, "height"))) gst_structure_set_value (s, "height", val); if ((val = gst_structure_get_value (allowed_s, "framerate"))) gst_structure_set_value (s, "framerate", val); if ((val = gst_structure_get_value (allowed_s, "pixel-aspect-ratio"))) gst_structure_set_value (s, "pixel-aspect-ratio", val); gst_caps_merge_structure (filter_caps, s); } } fcaps = gst_caps_intersect (filter_caps, templ_caps); gst_caps_unref (filter_caps); done: gst_caps_replace (&allowed, NULL); GST_LOG_OBJECT (base_video_encoder, "Returning caps %" GST_PTR_FORMAT, fcaps); return fcaps; }