static gboolean gst_gdiscreencapsrc_set_caps (GstBaseSrc * bsrc, GstCaps * caps) { GstGDIScreenCapSrc *src = GST_GDISCREENCAPSRC (bsrc); HWND capture; HDC device; GstStructure *structure; const GValue *framerate; gint red_mask, green_mask, blue_mask; gint bpp; structure = gst_caps_get_structure (caps, 0); gst_structure_get_int (structure, "red_mask", &red_mask); gst_structure_get_int (structure, "green_mask", &green_mask); gst_structure_get_int (structure, "blue_mask", &blue_mask); if (blue_mask != GST_VIDEO_BYTE1_MASK_24_INT || green_mask != GST_VIDEO_BYTE2_MASK_24_INT || red_mask != GST_VIDEO_BYTE3_MASK_24_INT) { GST_ERROR ("Wrong red_,green_,blue_ mask provided. " "We only support RGB and BGR"); return FALSE; } gst_structure_get_int (structure, "bpp", &bpp); if (bpp != 24) { GST_ERROR ("Wrong bpp provided %d. We only support 24 bpp", bpp); return FALSE; } src->src_rect = src->screen_rect; if (src->capture_w && src->capture_h) { src->src_rect.left += src->capture_x; src->src_rect.top += src->capture_y; src->src_rect.right = src->src_rect.left + src->capture_w; src->src_rect.bottom = src->src_rect.top + src->capture_h; } framerate = gst_structure_get_value (structure, "framerate"); if (framerate) { src->rate_numerator = gst_value_get_fraction_numerator (framerate); src->rate_denominator = gst_value_get_fraction_denominator (framerate); } src->info.bmiHeader.biSize = sizeof (BITMAPINFOHEADER); src->info.bmiHeader.biWidth = src->src_rect.right - src->src_rect.left; src->info.bmiHeader.biHeight = src->src_rect.top - src->src_rect.bottom; src->info.bmiHeader.biPlanes = 1; src->info.bmiHeader.biBitCount = 24; src->info.bmiHeader.biCompression = BI_RGB; src->info.bmiHeader.biSizeImage = 0; src->info.bmiHeader.biXPelsPerMeter = 0; src->info.bmiHeader.biYPelsPerMeter = 0; src->info.bmiHeader.biClrUsed = 0; src->info.bmiHeader.biClrImportant = 0; /* Cleanup first */ if (src->hBitmap != INVALID_HANDLE_VALUE) DeleteObject (src->hBitmap); if (src->memDC != INVALID_HANDLE_VALUE) DeleteDC (src->memDC); /* Allocate */ capture = GetDesktopWindow (); device = GetDC (capture); src->hBitmap = CreateDIBSection (device, &(src->info), DIB_RGB_COLORS, (void **) &(src->dibMem), 0, 0); src->memDC = CreateCompatibleDC (device); SelectObject (src->memDC, src->hBitmap); ReleaseDC (capture, device); GST_DEBUG_OBJECT (src, "size %dx%d, %d/%d fps", (gint) src->info.bmiHeader.biWidth, (gint) (-src->info.bmiHeader.biHeight), src->rate_numerator, src->rate_denominator); return TRUE; }
static gboolean gst_rtp_L16_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps) { GstRtpL16Pay *rtpL16pay; GstStructure *structure; gint channels, rate; gboolean res; gchar *params; GstAudioChannelPosition *pos; const GstRTPChannelOrder *order; GstBaseRTPAudioPayload *basertpaudiopayload; basertpaudiopayload = GST_BASE_RTP_AUDIO_PAYLOAD (basepayload); rtpL16pay = GST_RTP_L16_PAY (basepayload); structure = gst_caps_get_structure (caps, 0); /* first parse input caps */ if (!gst_structure_get_int (structure, "rate", &rate)) goto no_rate; if (!gst_structure_get_int (structure, "channels", &channels)) goto no_channels; /* get the channel order */ pos = gst_audio_get_channel_positions (structure); if (pos) order = gst_rtp_channels_get_by_pos (channels, pos); else order = NULL; gst_basertppayload_set_options (basepayload, "audio", TRUE, "L16", rate); params = g_strdup_printf ("%d", channels); if (!order && channels > 2) { GST_ELEMENT_WARNING (rtpL16pay, STREAM, DECODE, (NULL), ("Unknown channel order for %d channels", channels)); } if (order && order->name) { res = gst_basertppayload_set_outcaps (basepayload, "encoding-params", G_TYPE_STRING, params, "channels", G_TYPE_INT, channels, "channel-order", G_TYPE_STRING, order->name, NULL); } else { res = gst_basertppayload_set_outcaps (basepayload, "encoding-params", G_TYPE_STRING, params, "channels", G_TYPE_INT, channels, NULL); } g_free (params); g_free (pos); rtpL16pay->rate = rate; rtpL16pay->channels = channels; /* octet-per-sample is 2 * channels for L16 */ gst_base_rtp_audio_payload_set_sample_options (basertpaudiopayload, 2 * rtpL16pay->channels); return res; /* ERRORS */ no_rate: { GST_DEBUG_OBJECT (rtpL16pay, "no rate given"); return FALSE; } no_channels: { GST_DEBUG_OBJECT (rtpL16pay, "no channels given"); return FALSE; } }
static gboolean gst_rtp_bv_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps) { GstRTPBVDepay *rtpbvdepay = GST_RTP_BV_DEPAY (depayload); GstCaps *srccaps; GstStructure *structure; const gchar *mode_str = NULL; gint mode, clock_rate, expected_rate; gboolean ret; structure = gst_caps_get_structure (caps, 0); mode_str = gst_structure_get_string (structure, "encoding-name"); if (!mode_str) goto no_mode; if (!strcmp (mode_str, "BV16")) { mode = 16; expected_rate = 8000; } else if (!strcmp (mode_str, "BV32")) { mode = 32; expected_rate = 16000; } else goto invalid_mode; if (!gst_structure_get_int (structure, "clock-rate", &clock_rate)) clock_rate = expected_rate; else if (clock_rate != expected_rate) goto wrong_rate; depayload->clock_rate = clock_rate; rtpbvdepay->mode = mode; srccaps = gst_caps_new_simple ("audio/x-bv", "mode", G_TYPE_INT, rtpbvdepay->mode, NULL); ret = gst_pad_set_caps (GST_RTP_BASE_DEPAYLOAD_SRCPAD (depayload), srccaps); GST_DEBUG ("set caps on source: %" GST_PTR_FORMAT " (ret=%d)", srccaps, ret); gst_caps_unref (srccaps); return ret; /* ERRORS */ no_mode: { GST_ERROR_OBJECT (rtpbvdepay, "did not receive an encoding-name"); return FALSE; } invalid_mode: { GST_ERROR_OBJECT (rtpbvdepay, "invalid encoding-name, expected BV16 or BV32, got %s", mode_str); return FALSE; } wrong_rate: { GST_ERROR_OBJECT (rtpbvdepay, "invalid clock-rate, expected %d, got %d", expected_rate, clock_rate); return FALSE; } }
/** * gst_basertppayload_set_outcaps: * @payload: a #GstBaseRTPPayload * @fieldname: the first field name or %NULL * @...: field values * * Configure the output caps with the optional parameters. * * Variable arguments should be in the form field name, field type * (as a GType), value(s). The last variable argument should be NULL. * * Returns: %TRUE if the caps could be set. */ gboolean gst_basertppayload_set_outcaps (GstBaseRTPPayload * payload, gchar * fieldname, ...) { GstCaps *srccaps, *peercaps; gboolean res; /* fill in the defaults, there properties cannot be negotiated. */ srccaps = gst_caps_new_simple ("application/x-rtp", "media", G_TYPE_STRING, payload->media, "clock-rate", G_TYPE_INT, payload->clock_rate, "encoding-name", G_TYPE_STRING, payload->encoding_name, NULL); GST_DEBUG_OBJECT (payload, "defaults: %" GST_PTR_FORMAT, srccaps); if (fieldname) { va_list varargs; /* override with custom properties */ va_start (varargs, fieldname); gst_caps_set_simple_valist (srccaps, fieldname, varargs); va_end (varargs); GST_DEBUG_OBJECT (payload, "custom added: %" GST_PTR_FORMAT, srccaps); } /* the peer caps can override some of the defaults */ peercaps = gst_pad_peer_get_caps (payload->srcpad); if (peercaps == NULL) { /* no peer caps, just add the other properties */ gst_caps_set_simple (srccaps, "payload", G_TYPE_INT, GST_BASE_RTP_PAYLOAD_PT (payload), "ssrc", G_TYPE_UINT, payload->current_ssrc, "clock-base", G_TYPE_UINT, payload->ts_base, "seqnum-base", G_TYPE_UINT, payload->seqnum_base, NULL); GST_DEBUG_OBJECT (payload, "no peer caps: %" GST_PTR_FORMAT, srccaps); } else { GstCaps *temp; GstStructure *s, *d; const GValue *value; gint pt; /* peer provides caps we can use to fixate, intersect. This always returns a * writable caps. */ temp = gst_caps_intersect (srccaps, peercaps); gst_caps_unref (srccaps); gst_caps_unref (peercaps); /* now fixate, start by taking the first caps */ gst_caps_truncate (temp); /* get first structure */ s = gst_caps_get_structure (temp, 0); if (gst_structure_get_int (s, "payload", &pt)) { /* use peer pt */ GST_BASE_RTP_PAYLOAD_PT (payload) = pt; GST_LOG_OBJECT (payload, "using peer pt %d", pt); } else { if (gst_structure_has_field (s, "payload")) { /* can only fixate if there is a field */ gst_structure_fixate_field_nearest_int (s, "payload", GST_BASE_RTP_PAYLOAD_PT (payload)); gst_structure_get_int (s, "payload", &pt); GST_LOG_OBJECT (payload, "using peer pt %d", pt); } else { /* no pt field, use the internal pt */ pt = GST_BASE_RTP_PAYLOAD_PT (payload); gst_structure_set (s, "payload", G_TYPE_INT, pt, NULL); GST_LOG_OBJECT (payload, "using internal pt %d", pt); } } if (gst_structure_has_field_typed (s, "ssrc", G_TYPE_UINT)) { value = gst_structure_get_value (s, "ssrc"); payload->current_ssrc = g_value_get_uint (value); GST_LOG_OBJECT (payload, "using peer ssrc %08x", payload->current_ssrc); } else { /* FIXME, fixate_nearest_uint would be even better */ gst_structure_set (s, "ssrc", G_TYPE_UINT, payload->current_ssrc, NULL); GST_LOG_OBJECT (payload, "using internal ssrc %08x", payload->current_ssrc); } if (gst_structure_has_field_typed (s, "clock-base", G_TYPE_UINT)) { value = gst_structure_get_value (s, "clock-base"); payload->ts_base = g_value_get_uint (value); GST_LOG_OBJECT (payload, "using peer clock-base %u", payload->ts_base); } else { /* FIXME, fixate_nearest_uint would be even better */ gst_structure_set (s, "clock-base", G_TYPE_UINT, payload->ts_base, NULL); GST_LOG_OBJECT (payload, "using internal clock-base %u", payload->ts_base); } if (gst_structure_has_field_typed (s, "seqnum-base", G_TYPE_UINT)) { value = gst_structure_get_value (s, "seqnum-base"); payload->seqnum_base = g_value_get_uint (value); GST_LOG_OBJECT (payload, "using peer seqnum-base %u", payload->seqnum_base); } else { /* FIXME, fixate_nearest_uint would be even better */ gst_structure_set (s, "seqnum-base", G_TYPE_UINT, payload->seqnum_base, NULL); GST_LOG_OBJECT (payload, "using internal seqnum-base %u", payload->seqnum_base); } /* make the target caps by copying over all the fixed caps, removing the * unfixed caps. */ srccaps = gst_caps_new_simple (gst_structure_get_name (s), NULL); d = gst_caps_get_structure (srccaps, 0); gst_structure_foreach (s, (GstStructureForeachFunc) copy_fixed, d); gst_caps_unref (temp); GST_DEBUG_OBJECT (payload, "with peer caps: %" GST_PTR_FORMAT, srccaps); } res = gst_pad_set_caps (GST_BASE_RTP_PAYLOAD_SRCPAD (payload), srccaps); gst_caps_unref (srccaps); return res; }
static GstFlowReturn gst_a52dec_handle_frame (GstAudioDecoder * bdec, GstBuffer * buffer) { GstA52Dec *a52dec; gint channels, i; gboolean need_reneg = FALSE; gint chans; gint length = 0, flags, sample_rate, bit_rate; GstMapInfo map; GstFlowReturn result = GST_FLOW_OK; GstBuffer *outbuf; const gint num_blocks = 6; a52dec = GST_A52DEC (bdec); /* no fancy draining */ if (G_UNLIKELY (!buffer)) return GST_FLOW_OK; /* parsed stuff already, so this should work out fine */ gst_buffer_map (buffer, &map, GST_MAP_READ); g_assert (map.size >= 7); /* re-obtain some sync header info, * should be same as during _parse and could also be cached there, * but anyway ... */ bit_rate = a52dec->bit_rate; sample_rate = a52dec->sample_rate; flags = 0; length = a52_syncinfo (map.data, &flags, &sample_rate, &bit_rate); g_assert (length == map.size); /* update stream information, renegotiate or re-streaminfo if needed */ need_reneg = FALSE; if (a52dec->sample_rate != sample_rate) { GST_DEBUG_OBJECT (a52dec, "sample rate changed"); need_reneg = TRUE; a52dec->sample_rate = sample_rate; } if (flags) { if (a52dec->stream_channels != (flags & (A52_CHANNEL_MASK | A52_LFE))) { GST_DEBUG_OBJECT (a52dec, "stream channel flags changed, marking update"); a52dec->flag_update = TRUE; } a52dec->stream_channels = flags & (A52_CHANNEL_MASK | A52_LFE); } if (bit_rate != a52dec->bit_rate) { a52dec->bit_rate = bit_rate; gst_a52dec_update_streaminfo (a52dec); } /* If we haven't had an explicit number of channels chosen through properties * at this point, choose what to downmix to now, based on what the peer will * accept - this allows a52dec to do downmixing in preference to a * downstream element such as audioconvert. */ if (a52dec->request_channels != A52_CHANNEL) { flags = a52dec->request_channels; } else if (a52dec->flag_update) { GstCaps *caps; a52dec->flag_update = FALSE; caps = gst_pad_get_allowed_caps (GST_AUDIO_DECODER_SRC_PAD (a52dec)); if (caps && gst_caps_get_size (caps) > 0) { GstCaps *copy = gst_caps_copy_nth (caps, 0); GstStructure *structure = gst_caps_get_structure (copy, 0); gint orig_channels = flags ? gst_a52dec_channels (flags, NULL) : 6; gint fixed_channels = 0; const int a52_channels[6] = { A52_MONO, A52_STEREO, A52_STEREO | A52_LFE, A52_2F2R, A52_2F2R | A52_LFE, A52_3F2R | A52_LFE, }; /* Prefer the original number of channels, but fixate to something * preferred (first in the caps) downstream if possible. */ gst_structure_fixate_field_nearest_int (structure, "channels", orig_channels); if (gst_structure_get_int (structure, "channels", &fixed_channels) && fixed_channels <= 6) { if (fixed_channels < orig_channels) flags = a52_channels[fixed_channels - 1]; } else { flags = a52_channels[5]; } gst_caps_unref (copy); } else if (flags) flags = a52dec->stream_channels; else flags = A52_3F2R | A52_LFE; if (caps) gst_caps_unref (caps); } else { flags = a52dec->using_channels; } /* process */ flags |= A52_ADJUST_LEVEL; a52dec->level = 1; if (a52_frame (a52dec->state, map.data, &flags, &a52dec->level, a52dec->bias)) { gst_buffer_unmap (buffer, &map); GST_AUDIO_DECODER_ERROR (a52dec, 1, STREAM, DECODE, (NULL), ("a52_frame error"), result); goto exit; } gst_buffer_unmap (buffer, &map); channels = flags & (A52_CHANNEL_MASK | A52_LFE); if (a52dec->using_channels != channels) { need_reneg = TRUE; a52dec->using_channels = channels; } /* negotiate if required */ if (need_reneg) { GST_DEBUG_OBJECT (a52dec, "a52dec reneg: sample_rate:%d stream_chans:%d using_chans:%d", a52dec->sample_rate, a52dec->stream_channels, a52dec->using_channels); if (!gst_a52dec_reneg (a52dec)) goto failed_negotiation; } if (a52dec->dynamic_range_compression == FALSE) { a52_dynrng (a52dec->state, NULL, NULL); } flags &= (A52_CHANNEL_MASK | A52_LFE); chans = gst_a52dec_channels (flags, NULL); if (!chans) goto invalid_flags; /* handle decoded data; * each frame has 6 blocks, one block is 256 samples, ea */ outbuf = gst_buffer_new_and_alloc (256 * chans * (SAMPLE_WIDTH / 8) * num_blocks); gst_buffer_map (outbuf, &map, GST_MAP_WRITE); { guint8 *ptr = map.data; for (i = 0; i < num_blocks; i++) { if (a52_block (a52dec->state)) { /* also marks discont */ GST_AUDIO_DECODER_ERROR (a52dec, 1, STREAM, DECODE, (NULL), ("error decoding block %d", i), result); if (result != GST_FLOW_OK) { gst_buffer_unmap (outbuf, &map); goto exit; } } else { gint n, c; gint *reorder_map = a52dec->channel_reorder_map; for (n = 0; n < 256; n++) { for (c = 0; c < chans; c++) { ((sample_t *) ptr)[n * chans + reorder_map[c]] = a52dec->samples[c * 256 + n]; } } } ptr += 256 * chans * (SAMPLE_WIDTH / 8); } } gst_buffer_unmap (outbuf, &map); result = gst_audio_decoder_finish_frame (bdec, outbuf, 1); exit: return result; /* ERRORS */ failed_negotiation: { GST_ELEMENT_ERROR (a52dec, CORE, NEGOTIATION, (NULL), (NULL)); return GST_FLOW_ERROR; } invalid_flags: { GST_ELEMENT_ERROR (GST_ELEMENT (a52dec), STREAM, DECODE, (NULL), ("Invalid channel flags: %d", flags)); return GST_FLOW_ERROR; } }
static gboolean gst_wavenc_sink_setcaps (GstPad * pad, GstCaps * caps) { GstWavEnc *wavenc; GstStructure *structure; const gchar *name; gint chans, rate; GstCaps *ccaps; wavenc = GST_WAVENC (gst_pad_get_parent (pad)); ccaps = gst_pad_get_current_caps (pad); if (wavenc->sent_header && ccaps && !gst_caps_can_intersect (caps, ccaps)) { gst_caps_unref (ccaps); GST_WARNING_OBJECT (wavenc, "cannot change format in middle of stream"); goto fail; } if (ccaps) gst_caps_unref (ccaps); GST_DEBUG_OBJECT (wavenc, "got caps: %" GST_PTR_FORMAT, caps); structure = gst_caps_get_structure (caps, 0); name = gst_structure_get_name (structure); if (!gst_structure_get_int (structure, "channels", &chans) || !gst_structure_get_int (structure, "rate", &rate)) { GST_WARNING_OBJECT (wavenc, "caps incomplete"); goto fail; } if (strcmp (name, "audio/x-raw") == 0) { GstAudioInfo info; if (!gst_audio_info_from_caps (&info, caps)) goto fail; if (GST_AUDIO_INFO_IS_INTEGER (&info)) wavenc->format = GST_RIFF_WAVE_FORMAT_PCM; else if (GST_AUDIO_INFO_IS_FLOAT (&info)) wavenc->format = GST_RIFF_WAVE_FORMAT_IEEE_FLOAT; else goto fail; wavenc->width = GST_AUDIO_INFO_WIDTH (&info); } else if (strcmp (name, "audio/x-alaw") == 0) { wavenc->format = GST_RIFF_WAVE_FORMAT_ALAW; wavenc->width = 8; } else if (strcmp (name, "audio/x-mulaw") == 0) { wavenc->format = GST_RIFF_WAVE_FORMAT_MULAW; wavenc->width = 8; } else { GST_WARNING_OBJECT (wavenc, "Unsupported format %s", name); goto fail; } wavenc->channels = chans; wavenc->rate = rate; GST_LOG_OBJECT (wavenc, "accepted caps: format=0x%04x chans=%u width=%u rate=%u", wavenc->format, wavenc->channels, wavenc->width, wavenc->rate); gst_object_unref (wavenc); return TRUE; fail: gst_object_unref (wavenc); return FALSE; }
static GstFlowReturn mpegpsmux_create_stream (MpegPsMux * mux, MpegPsPadData * ps_data, GstPad * pad) { /* Create a steam. Fill in codec specific information */ GstFlowReturn ret = GST_FLOW_ERROR; GstCaps *caps = gst_pad_get_negotiated_caps (pad); GstStructure *s; if (caps == NULL) { GST_DEBUG_OBJECT (pad, "Sink pad caps were not set before pushing"); return GST_FLOW_NOT_NEGOTIATED; } s = gst_caps_get_structure (caps, 0); g_return_val_if_fail (s != NULL, FALSE); if (gst_structure_has_name (s, "video/x-dirac")) { GST_DEBUG_OBJECT (pad, "Creating Dirac stream"); ps_data->stream = psmux_create_stream (mux->psmux, PSMUX_ST_VIDEO_DIRAC); } else if (gst_structure_has_name (s, "audio/x-ac3")) { GST_DEBUG_OBJECT (pad, "Creating AC3 stream"); ps_data->stream = psmux_create_stream (mux->psmux, PSMUX_ST_PS_AUDIO_AC3); } else if (gst_structure_has_name (s, "audio/x-dts")) { GST_DEBUG_OBJECT (pad, "Creating DTS stream"); ps_data->stream = psmux_create_stream (mux->psmux, PSMUX_ST_PS_AUDIO_DTS); } else if (gst_structure_has_name (s, "audio/x-lpcm")) { GST_DEBUG_OBJECT (pad, "Creating LPCM stream"); ps_data->stream = psmux_create_stream (mux->psmux, PSMUX_ST_PS_AUDIO_LPCM); } else if (gst_structure_has_name (s, "video/x-h264")) { const GValue *value; GST_DEBUG_OBJECT (pad, "Creating H264 stream"); /* Codec data contains SPS/PPS which need to go in stream for valid ES */ value = gst_structure_get_value (s, "codec_data"); if (value) { ps_data->codec_data = gst_buffer_ref (gst_value_get_buffer (value)); GST_DEBUG_OBJECT (pad, "we have additional codec data (%d bytes)", GST_BUFFER_SIZE (ps_data->codec_data)); ps_data->prepare_func = mpegpsmux_prepare_h264; } else { ps_data->codec_data = NULL; } ps_data->stream = psmux_create_stream (mux->psmux, PSMUX_ST_VIDEO_H264); } else if (gst_structure_has_name (s, "audio/mpeg")) { gint mpegversion; if (!gst_structure_get_int (s, "mpegversion", &mpegversion)) { GST_ELEMENT_ERROR (pad, STREAM, FORMAT, ("Invalid data format presented"), ("Caps with type audio/mpeg did not have mpegversion")); goto beach; } switch (mpegversion) { case 1: GST_DEBUG_OBJECT (pad, "Creating MPEG Audio, version 1 stream"); ps_data->stream = psmux_create_stream (mux->psmux, PSMUX_ST_AUDIO_MPEG1); break; case 2: GST_DEBUG_OBJECT (pad, "Creating MPEG Audio, version 2 stream"); ps_data->stream = psmux_create_stream (mux->psmux, PSMUX_ST_AUDIO_MPEG2); break; case 4: { const GValue *value; /* Codec data contains SPS/PPS which need to go in stream for valid ES */ GST_DEBUG_OBJECT (pad, "Creating MPEG Audio, version 4 stream"); value = gst_structure_get_value (s, "codec_data"); if (value) { ps_data->codec_data = gst_buffer_ref (gst_value_get_buffer (value)); GST_DEBUG_OBJECT (pad, "we have additional codec data (%d bytes)", GST_BUFFER_SIZE (ps_data->codec_data)); ps_data->prepare_func = mpegpsmux_prepare_aac; } else { ps_data->codec_data = NULL; } ps_data->stream = psmux_create_stream (mux->psmux, PSMUX_ST_AUDIO_AAC); break; } default: GST_WARNING_OBJECT (pad, "unsupported mpegversion %d", mpegversion); goto beach; } } else if (gst_structure_has_name (s, "video/mpeg")) { gint mpegversion; if (!gst_structure_get_int (s, "mpegversion", &mpegversion)) { GST_ELEMENT_ERROR (mux, STREAM, FORMAT, ("Invalid data format presented"), ("Caps with type video/mpeg did not have mpegversion")); goto beach; } if (mpegversion == 1) { GST_DEBUG_OBJECT (pad, "Creating MPEG Video, version 1 stream"); ps_data->stream = psmux_create_stream (mux->psmux, PSMUX_ST_VIDEO_MPEG1); } else if (mpegversion == 2) { GST_DEBUG_OBJECT (pad, "Creating MPEG Video, version 2 stream"); ps_data->stream = psmux_create_stream (mux->psmux, PSMUX_ST_VIDEO_MPEG2); } else { GST_DEBUG_OBJECT (pad, "Creating MPEG Video, version 4 stream"); ps_data->stream = psmux_create_stream (mux->psmux, PSMUX_ST_VIDEO_MPEG4); } } if (ps_data->stream != NULL) { ps_data->stream_id = ps_data->stream->stream_id; ps_data->stream_id_ext = ps_data->stream->stream_id_ext; GST_DEBUG_OBJECT (pad, "Stream created, stream_id=%04x, stream_id_ext=%04x", ps_data->stream_id , ps_data->stream_id_ext); gst_structure_get_int (s, "rate", &ps_data->stream->audio_sampling); gst_structure_get_int (s, "channels", &ps_data->stream->audio_channels); gst_structure_get_int (s, "bitrate", &ps_data->stream->audio_bitrate); psmux_stream_set_buffer_release_func (ps_data->stream, release_buffer_cb); ret = GST_FLOW_OK; } beach: return ret; }
static gboolean _add_clip(GstValidateScenario *scenario, GstValidateAction * action) { GESTimeline *timeline = get_timeline(scenario); GESAsset *asset; GESLayer *layer; GESClip *clip; GError *error = NULL; gint layer_priority; const gchar *name; const gchar *asset_id; const gchar *type_string; GType type; gboolean res = FALSE; GstClockTime duration = 1 * GST_SECOND; gst_structure_get_int(action->structure, "layer-priority", &layer_priority); name = gst_structure_get_string(action->structure, "name"); asset_id = gst_structure_get_string(action->structure, "asset-id"); type_string = gst_structure_get_string(action->structure, "type"); if (!(type = g_type_from_name(type_string))) { GST_ERROR("This type doesn't exist : %s", type_string); goto beach; } asset = ges_asset_request(type, asset_id, &error); if (!asset || error) { GST_ERROR("There was an error requesting the asset with id %s and type %s (%s)", asset_id, type_string, error->message); goto beach; } layer = _get_layer_by_priority(timeline, layer_priority); if (!layer) { GST_ERROR("No layer with priority %d", layer_priority); goto beach; } if (type == GES_TYPE_URI_CLIP) { duration = GST_CLOCK_TIME_NONE; } clip = ges_layer_add_asset(layer, asset, GST_CLOCK_TIME_NONE, 0, duration, GES_TRACK_TYPE_UNKNOWN); if (clip) { res = TRUE; if (!ges_timeline_element_set_name(GES_TIMELINE_ELEMENT(clip), name)) { res = FALSE; GST_ERROR("couldn't set name %s on clip with id %s", name, asset_id); } } else { GST_ERROR("Couldn't add clip with id %s to layer with priority %d", asset_id, layer_priority); } gst_object_unref (layer); ges_timeline_commit(timeline); beach: g_object_unref(timeline); return res; }
static gboolean _edit_clip (GstValidateScenario * scenario, GstValidateAction * action) { gint64 cpos; gdouble rate; GList *layers = NULL; GESTimeline *timeline; GstQuery *query_segment; GESTimelineElement *clip; GstClockTime position; gint64 stop_value; gboolean res = FALSE; gint new_layer_priority = -1; GESEditMode edge = GES_EDGE_NONE; GESEditMode mode = GES_EDIT_MODE_NORMAL; const gchar *edit_mode_str = NULL, *edge_str = NULL; const gchar *clip_name; clip_name = gst_structure_get_string (action->structure, "clip-name"); timeline = get_timeline (scenario); g_return_val_if_fail (timeline, FALSE); clip = ges_timeline_get_element (timeline, clip_name); g_return_val_if_fail (GES_IS_CLIP (clip), FALSE); if (!gst_validate_action_get_clocktime (scenario, action, "position", &position)) { GST_WARNING ("Could not get position"); goto beach; } if ((edit_mode_str = gst_structure_get_string (action->structure, "edit-mode"))) g_return_val_if_fail (gst_validate_utils_enum_from_str (GES_TYPE_EDIT_MODE, edit_mode_str, &mode), FALSE); if ((edge_str = gst_structure_get_string (action->structure, "edge"))) g_return_val_if_fail (gst_validate_utils_enum_from_str (GES_TYPE_EDGE, edge_str, &edge), FALSE); gst_structure_get_int (action->structure, "new-layer-priority", &new_layer_priority); gst_validate_printf (action, "Editing %s to %" GST_TIME_FORMAT " in %s mode, edge: %s " "with new layer prio: %d \n\n", clip_name, GST_TIME_ARGS (position), edit_mode_str ? edit_mode_str : "normal", edge_str ? edge_str : "None", new_layer_priority); if (!ges_container_edit (GES_CONTAINER (clip), layers, new_layer_priority, mode, edge, position)) { gst_object_unref (clip); goto beach; } gst_object_unref (clip); query_segment = gst_query_new_segment (GST_FORMAT_TIME); if (!gst_element_query (scenario->pipeline, query_segment)) { GST_ERROR_OBJECT (scenario, "Could not query segment"); goto beach; } if (!gst_element_query_position (scenario->pipeline, GST_FORMAT_TIME, &cpos)) { GST_ERROR_OBJECT (scenario, "Could not query position"); goto beach; } if (!ges_timeline_commit (timeline)) { GST_DEBUG_OBJECT (scenario, "nothing changed, no need to seek"); res = TRUE; goto beach; } gst_query_parse_segment (query_segment, &rate, NULL, NULL, &stop_value); res = gst_validate_scenario_execute_seek (scenario, action, rate, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, cpos, GST_SEEK_TYPE_SET, stop_value); beach: g_object_unref(timeline); return res; }
// checkBuffer void gstCamera::checkBuffer() { if( !mAppSink ) return; // block waiting for the buffer GstSample* gstSample = gst_app_sink_pull_sample(mAppSink); if( !gstSample ) { printf(LOG_GSTREAMER "gstreamer camera -- gst_app_sink_pull_sample() returned NULL...\n"); return; } GstBuffer* gstBuffer = gst_sample_get_buffer(gstSample); if( !gstBuffer ) { printf(LOG_GSTREAMER "gstreamer camera -- gst_sample_get_buffer() returned NULL...\n"); return; } // retrieve GstMapInfo map; if( !gst_buffer_map(gstBuffer, &map, GST_MAP_READ) ) { printf(LOG_GSTREAMER "gstreamer camera -- gst_buffer_map() failed...\n"); return; } //gst_util_dump_mem(map.data, map.size); void* gstData = map.data; //GST_BUFFER_DATA(gstBuffer); const uint32_t gstSize = map.size; //GST_BUFFER_SIZE(gstBuffer); if( !gstData ) { printf(LOG_GSTREAMER "gstreamer camera -- gst_buffer had NULL data pointer...\n"); release_return; } // retrieve caps GstCaps* gstCaps = gst_sample_get_caps(gstSample); if( !gstCaps ) { printf(LOG_GSTREAMER "gstreamer camera -- gst_buffer had NULL caps...\n"); release_return; } GstStructure* gstCapsStruct = gst_caps_get_structure(gstCaps, 0); if( !gstCapsStruct ) { printf(LOG_GSTREAMER "gstreamer camera -- gst_caps had NULL structure...\n"); release_return; } // get width & height of the buffer int width = 0; int height = 0; if( !gst_structure_get_int(gstCapsStruct, "width", &width) || !gst_structure_get_int(gstCapsStruct, "height", &height) ) { printf(LOG_GSTREAMER "gstreamer camera -- gst_caps missing width/height...\n"); release_return; } if( width < 1 || height < 1 ) release_return; mWidth = width; mHeight = height; mDepth = (gstSize * 8) / (width * height); mSize = gstSize; //printf(LOG_GSTREAMER "gstreamer camera recieved %ix%i frame (%u bytes, %u bpp)\n", width, height, gstSize, mDepth); // make sure ringbuffer is allocated if( !mRingbufferCPU[0] ) { for( uint32_t n=0; n < NUM_RINGBUFFERS; n++ ) { if( !cudaAllocMapped(&mRingbufferCPU[n], &mRingbufferGPU[n], gstSize) ) printf(LOG_CUDA "gstreamer camera -- failed to allocate ringbuffer %u (size=%u)\n", n, gstSize); } printf(LOG_CUDA "gstreamer camera -- allocated %u ringbuffers, %u bytes each\n", NUM_RINGBUFFERS, gstSize); } // copy to next ringbuffer const uint32_t nextRingbuffer = (mLatestRingbuffer + 1) % NUM_RINGBUFFERS; //printf(LOG_GSTREAMER "gstreamer camera -- using ringbuffer #%u for next frame\n", nextRingbuffer); memcpy(mRingbufferCPU[nextRingbuffer], gstData, gstSize); gst_buffer_unmap(gstBuffer, &map); //gst_buffer_unref(gstBuffer); gst_sample_unref(gstSample); // update and signal sleeping threads mRingMutex->lock(); mLatestRingbuffer = nextRingbuffer; mLatestRetrieved = false; mRingMutex->unlock(); mWaitEvent->wakeAll(); }
static gboolean gst_aravis_set_caps (GstBaseSrc *src, GstCaps *caps) { GstAravis* gst_aravis = GST_ARAVIS(src); GstStructure *structure; ArvPixelFormat pixel_format; int height, width; int bpp, depth; const GValue *frame_rate; const char *caps_string; unsigned int i; guint32 fourcc; GST_LOG_OBJECT (gst_aravis, "Requested caps = %" GST_PTR_FORMAT, caps); arv_camera_stop_acquisition (gst_aravis->camera); if (gst_aravis->stream != NULL) g_object_unref (gst_aravis->stream); structure = gst_caps_get_structure (caps, 0); gst_structure_get_int (structure, "width", &width); gst_structure_get_int (structure, "height", &height); frame_rate = gst_structure_get_value (structure, "framerate"); gst_structure_get_int (structure, "bpp", &bpp); gst_structure_get_int (structure, "depth", &depth); if (gst_structure_get_field_type (structure, "format") == G_TYPE_STRING) { const char *string; string = gst_structure_get_string (structure, "format"); fourcc = GST_STR_FOURCC (string); } else if (gst_structure_get_field_type (structure, "format") == GST_TYPE_FOURCC) { gst_structure_get_fourcc (structure, "format", &fourcc); } else fourcc = 0; pixel_format = arv_pixel_format_from_gst_caps (gst_structure_get_name (structure), bpp, depth, fourcc); arv_camera_set_region (gst_aravis->camera, gst_aravis->offset_x, gst_aravis->offset_y, width, height); arv_camera_set_binning (gst_aravis->camera, gst_aravis->h_binning, gst_aravis->v_binning); arv_camera_set_pixel_format (gst_aravis->camera, pixel_format); if (frame_rate != NULL) { double dbl_frame_rate; dbl_frame_rate = (double) gst_value_get_fraction_numerator (frame_rate) / (double) gst_value_get_fraction_denominator (frame_rate); GST_DEBUG_OBJECT (gst_aravis, "Frame rate = %g Hz", dbl_frame_rate); arv_camera_set_frame_rate (gst_aravis->camera, dbl_frame_rate); if (dbl_frame_rate > 0.0) gst_aravis->buffer_timeout_us = MAX (GST_ARAVIS_BUFFER_TIMEOUT_DEFAULT, 3e6 / dbl_frame_rate); else gst_aravis->buffer_timeout_us = GST_ARAVIS_BUFFER_TIMEOUT_DEFAULT; } else gst_aravis->buffer_timeout_us = GST_ARAVIS_BUFFER_TIMEOUT_DEFAULT; GST_DEBUG_OBJECT (gst_aravis, "Buffer timeout = %Ld µs", gst_aravis->buffer_timeout_us); GST_DEBUG_OBJECT (gst_aravis, "Actual frame rate = %g Hz", arv_camera_get_frame_rate (gst_aravis->camera)); if(gst_aravis->gain_auto) { arv_camera_set_gain_auto (gst_aravis->camera, ARV_AUTO_CONTINUOUS); GST_DEBUG_OBJECT (gst_aravis, "Auto Gain = continuous", gst_aravis->gain_auto); } else { if (gst_aravis->gain >= 0) { GST_DEBUG_OBJECT (gst_aravis, "Gain = %d", gst_aravis->gain); arv_camera_set_gain_auto (gst_aravis->camera, ARV_AUTO_OFF); arv_camera_set_gain (gst_aravis->camera, gst_aravis->gain); } GST_DEBUG_OBJECT (gst_aravis, "Actual gain = %d", arv_camera_get_gain (gst_aravis->camera)); } if(gst_aravis->exposure_auto) { arv_camera_set_exposure_time_auto (gst_aravis->camera, ARV_AUTO_CONTINUOUS); GST_DEBUG_OBJECT (gst_aravis, "Auto Exposure = contiuous", gst_aravis->exposure_auto); } else { if (gst_aravis->exposure_time_us > 0.0) { GST_DEBUG_OBJECT (gst_aravis, "Exposure = %g µs", gst_aravis->exposure_time_us); arv_camera_set_exposure_time_auto (gst_aravis->camera, ARV_AUTO_OFF); arv_camera_set_exposure_time (gst_aravis->camera, gst_aravis->exposure_time_us); } GST_DEBUG_OBJECT (gst_aravis, "Actual exposure = %g µs", arv_camera_get_exposure_time (gst_aravis->camera)); } if (gst_aravis->fixed_caps != NULL) gst_caps_unref (gst_aravis->fixed_caps); caps_string = arv_pixel_format_to_gst_caps_string (pixel_format); if (caps_string != NULL) { GstStructure *structure; GstCaps *caps; caps = gst_caps_new_empty (); structure = gst_structure_from_string (caps_string, NULL); gst_structure_set (structure, "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL); if (frame_rate != NULL) gst_structure_set_value (structure, "framerate", frame_rate); gst_caps_append_structure (caps, structure); gst_aravis->fixed_caps = caps; } else gst_aravis->fixed_caps = NULL; gst_aravis->payload = arv_camera_get_payload (gst_aravis->camera); gst_aravis->stream = arv_camera_create_stream (gst_aravis->camera, NULL, NULL); for (i = 0; i < GST_ARAVIS_N_BUFFERS; i++) arv_stream_push_buffer (gst_aravis->stream, arv_buffer_new (gst_aravis->payload, NULL)); GST_LOG_OBJECT (gst_aravis, "Start acquisition"); arv_camera_start_acquisition (gst_aravis->camera); gst_aravis->timestamp_offset = 0; gst_aravis->last_timestamp = 0; return TRUE; }
static gboolean gst_rtp_amr_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps) { GstStructure *structure; GstCaps *srccaps; GstRtpAMRDepay *rtpamrdepay; const gchar *params; const gchar *str, *type; gint clock_rate, need_clock_rate; gboolean res; rtpamrdepay = GST_RTP_AMR_DEPAY (depayload); structure = gst_caps_get_structure (caps, 0); /* figure out the mode first and set the clock rates */ if ((str = gst_structure_get_string (structure, "encoding-name"))) { if (strcmp (str, "AMR") == 0) { rtpamrdepay->mode = GST_RTP_AMR_DP_MODE_NB; need_clock_rate = 8000; type = "audio/AMR"; } else if (strcmp (str, "AMR-WB") == 0) { rtpamrdepay->mode = GST_RTP_AMR_DP_MODE_WB; need_clock_rate = 16000; type = "audio/AMR-WB"; } else goto invalid_mode; } else goto invalid_mode; if (!(str = gst_structure_get_string (structure, "octet-align"))) rtpamrdepay->octet_align = FALSE; else rtpamrdepay->octet_align = (atoi (str) == 1); if (!(str = gst_structure_get_string (structure, "crc"))) rtpamrdepay->crc = FALSE; else rtpamrdepay->crc = (atoi (str) == 1); if (rtpamrdepay->crc) { /* crc mode implies octet aligned mode */ rtpamrdepay->octet_align = TRUE; } if (!(str = gst_structure_get_string (structure, "robust-sorting"))) rtpamrdepay->robust_sorting = FALSE; else rtpamrdepay->robust_sorting = (atoi (str) == 1); if (rtpamrdepay->robust_sorting) { /* robust_sorting mode implies octet aligned mode */ rtpamrdepay->octet_align = TRUE; } if (!(str = gst_structure_get_string (structure, "interleaving"))) rtpamrdepay->interleaving = FALSE; else rtpamrdepay->interleaving = (atoi (str) == 1); if (rtpamrdepay->interleaving) { /* interleaving mode implies octet aligned mode */ rtpamrdepay->octet_align = TRUE; } if (!(params = gst_structure_get_string (structure, "encoding-params"))) rtpamrdepay->channels = 1; else { rtpamrdepay->channels = atoi (params); } if (!gst_structure_get_int (structure, "clock-rate", &clock_rate)) clock_rate = need_clock_rate; depayload->clock_rate = clock_rate; /* we require 1 channel, 8000 Hz, octet aligned, no CRC, * no robust sorting, no interleaving for now */ if (rtpamrdepay->channels != 1) return FALSE; if (clock_rate != need_clock_rate) return FALSE; if (rtpamrdepay->octet_align != TRUE) return FALSE; if (rtpamrdepay->robust_sorting != FALSE) return FALSE; if (rtpamrdepay->interleaving != FALSE) return FALSE; srccaps = gst_caps_new_simple (type, "channels", G_TYPE_INT, rtpamrdepay->channels, "rate", G_TYPE_INT, clock_rate, NULL); res = gst_pad_set_caps (GST_RTP_BASE_DEPAYLOAD_SRCPAD (depayload), srccaps); gst_caps_unref (srccaps); return res; /* ERRORS */ invalid_mode: { GST_ERROR_OBJECT (rtpamrdepay, "invalid encoding-name"); return FALSE; } }
/* h264 dec has its own sink_setcaps for supporting nalu convert codec data */ static gboolean sink_setcaps (GstPad * pad, GstCaps * caps) { GstStructure *structure; GstOmxBaseVideoDec *self; GstOmxH264Dec *h264_self; GstOmxBaseFilter *omx_base; GOmxCore *gomx; OMX_PARAM_PORTDEFINITIONTYPE param; gint width = 0; gint height = 0; self = GST_OMX_BASE_VIDEODEC (GST_PAD_PARENT (pad)); h264_self = GST_OMX_H264DEC (GST_PAD_PARENT (pad)); omx_base = GST_OMX_BASE_FILTER (self); gomx = (GOmxCore *) omx_base->gomx; GST_INFO_OBJECT (self, "setcaps (sink)(h264): %" GST_PTR_FORMAT, caps); g_return_val_if_fail (gst_caps_get_size (caps) == 1, FALSE); structure = gst_caps_get_structure (caps, 0); gst_structure_get_int (structure, "width", &width); gst_structure_get_int (structure, "height", &height); { const GValue *framerate = NULL; framerate = gst_structure_get_value (structure, "framerate"); if (framerate) { self->framerate_num = gst_value_get_fraction_numerator (framerate); self->framerate_denom = gst_value_get_fraction_denominator (framerate); } } G_OMX_INIT_PARAM (param); { const GValue *codec_data; GstBuffer *buffer; gboolean ret = FALSE; guint8 *buf_data = NULL; codec_data = gst_structure_get_value (structure, "codec_data"); if (codec_data) { buffer = gst_value_get_buffer (codec_data); buf_data = GST_BUFFER_DATA(buffer); if (GST_BUFFER_SIZE(buffer) < 4) GST_ERROR("codec data size is less than 4!!"); //check this. if ((buf_data[0] == 0x00)&&(buf_data[1] == 0x00)&& ((buf_data[2] == 0x01)||((buf_data[2] == 0x00)&&(buf_data[3] == 0x01)))) { h264_self->h264Format = GSTOMX_H264_FORMAT_NALU; GST_INFO_OBJECT(self, "H264 format is NALU"); } else { h264_self->h264Format = GSTOMX_H264_FORMAT_3GPP; GST_INFO_OBJECT(self, "H264 format is 3GPP"); } /* if codec data is 3gpp format, convert nalu format */ if(h264_self->h264Format == GSTOMX_H264_FORMAT_3GPP) { GstBuffer *nalu_dci = NULL; ret = convert_dci(h264_self, buffer, &nalu_dci); if (ret) { omx_base->codec_data = nalu_dci; } else { if (nalu_dci) { gst_buffer_unref (nalu_dci); } GST_ERROR_OBJECT(h264_self, "converting dci error."); omx_base->codec_data = buffer; gst_buffer_ref (buffer); } } else { /* not 3GPP format */ omx_base->codec_data = buffer; gst_buffer_ref (buffer); } h264_self->h264Format = GSTOMX_H264_FORMAT_UNKNOWN; } } /* Input port configuration. */ { param.nPortIndex = omx_base->in_port->port_index; OMX_GetParameter (gomx->omx_handle, OMX_IndexParamPortDefinition, ¶m); param.format.video.nFrameWidth = width; param.format.video.nFrameHeight = height; OMX_SetParameter (gomx->omx_handle, OMX_IndexParamPortDefinition, ¶m); } return gst_pad_set_caps (pad, caps); }
static gboolean gst_rdt_depay_setcaps (GstPad * pad, GstCaps * caps) { GstStructure *structure; GstRDTDepay *rdtdepay; GstCaps *srccaps; gint clock_rate = 1000; /* default */ const GValue *value; GstBuffer *header; rdtdepay = GST_RDT_DEPAY (GST_PAD_PARENT (pad)); structure = gst_caps_get_structure (caps, 0); if (gst_structure_has_field (structure, "clock-rate")) gst_structure_get_int (structure, "clock-rate", &clock_rate); /* config contains the RealMedia header as a buffer. */ value = gst_structure_get_value (structure, "config"); if (!value) goto no_header; header = gst_value_get_buffer (value); if (!header) goto no_header; /* get other values for newsegment */ value = gst_structure_get_value (structure, "npt-start"); if (value && G_VALUE_HOLDS_UINT64 (value)) rdtdepay->npt_start = g_value_get_uint64 (value); else rdtdepay->npt_start = 0; GST_DEBUG_OBJECT (rdtdepay, "NPT start %" G_GUINT64_FORMAT, rdtdepay->npt_start); value = gst_structure_get_value (structure, "npt-stop"); if (value && G_VALUE_HOLDS_UINT64 (value)) rdtdepay->npt_stop = g_value_get_uint64 (value); else rdtdepay->npt_stop = -1; GST_DEBUG_OBJECT (rdtdepay, "NPT stop %" G_GUINT64_FORMAT, rdtdepay->npt_stop); value = gst_structure_get_value (structure, "play-speed"); if (value && G_VALUE_HOLDS_DOUBLE (value)) rdtdepay->play_speed = g_value_get_double (value); else rdtdepay->play_speed = 1.0; value = gst_structure_get_value (structure, "play-scale"); if (value && G_VALUE_HOLDS_DOUBLE (value)) rdtdepay->play_scale = g_value_get_double (value); else rdtdepay->play_scale = 1.0; /* caps seem good, configure element */ rdtdepay->clock_rate = clock_rate; /* set caps on pad and on header */ srccaps = gst_caps_new_simple ("application/vnd.rn-realmedia", NULL); gst_pad_set_caps (rdtdepay->srcpad, srccaps); gst_caps_unref (srccaps); if (rdtdepay->header) gst_buffer_unref (rdtdepay->header); rdtdepay->header = gst_buffer_ref (header); return TRUE; /* ERRORS */ no_header: { GST_ERROR_OBJECT (rdtdepay, "no header found in caps, no 'config' field"); return FALSE; } }
static gboolean gst_y4m_encode_setcaps (GstPad * pad, GstCaps * vscaps) { GstY4mEncode *filter; GstStructure *structure; gboolean res; gint w, h; guint32 fourcc; const GValue *fps, *par, *interlaced; filter = GST_Y4M_ENCODE (GST_PAD_PARENT (pad)); structure = gst_caps_get_structure (vscaps, 0); res = gst_structure_get_int (structure, "width", &w); res &= gst_structure_get_int (structure, "height", &h); res &= ((fps = gst_structure_get_value (structure, "framerate")) != NULL); res &= gst_structure_get_fourcc (structure, "format", &fourcc); switch (fourcc) { /* Translate fourcc to Y4M colorspace code */ case GST_MAKE_FOURCC ('I', '4', '2', '0'): case GST_MAKE_FOURCC ('I', 'Y', 'U', 'V'): filter->colorspace = "420"; break; case GST_MAKE_FOURCC ('Y', '4', '2', 'B'): filter->colorspace = "422"; break; case GST_MAKE_FOURCC ('Y', '4', '1', 'B'): filter->colorspace = "411"; break; case GST_MAKE_FOURCC ('Y', '4', '4', '4'): filter->colorspace = "444"; break; default: res = FALSE; break; } if (!res || w <= 0 || h <= 0 || !GST_VALUE_HOLDS_FRACTION (fps)) return FALSE; /* optional interlaced info */ interlaced = gst_structure_get_value (structure, "interlaced"); /* optional par info */ par = gst_structure_get_value (structure, "pixel-aspect-ratio"); filter->width = w; filter->height = h; filter->fps_num = gst_value_get_fraction_numerator (fps); filter->fps_den = gst_value_get_fraction_denominator (fps); if ((par != NULL) && GST_VALUE_HOLDS_FRACTION (par)) { filter->par_num = gst_value_get_fraction_numerator (par); filter->par_den = gst_value_get_fraction_denominator (par); } else { /* indicates unknown */ filter->par_num = 0; filter->par_den = 0; } if ((interlaced != NULL) && G_VALUE_HOLDS (interlaced, G_TYPE_BOOLEAN)) { filter->interlaced = g_value_get_boolean (interlaced); } else { /* assume progressive if no interlaced property in caps */ filter->interlaced = FALSE; } /* the template caps will do for the src pad, should always accept */ return gst_pad_set_caps (filter->srcpad, gst_static_pad_template_get_caps (&y4mencode_src_factory)); }
static gboolean gst_omx_aac_dec_is_format_change (GstOMXAudioDec * dec, GstOMXPort * port, GstCaps * caps) { GstOMXAACDec *self = GST_OMX_AAC_DEC (dec); OMX_AUDIO_PARAM_AACPROFILETYPE aac_param; OMX_ERRORTYPE err; GstStructure *s; gint rate, channels, mpegversion; const gchar *stream_format; GST_OMX_INIT_STRUCT (&aac_param); aac_param.nPortIndex = port->index; err = gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioAac, &aac_param); if (err != OMX_ErrorNone) { GST_ERROR_OBJECT (self, "Failed to get AAC parameters from component: %s (0x%08x)", gst_omx_error_to_string (err), err); return FALSE; } s = gst_caps_get_structure (caps, 0); if (!gst_structure_get_int (s, "mpegversion", &mpegversion) || !gst_structure_get_int (s, "rate", &rate) || !gst_structure_get_int (s, "channels", &channels)) { GST_ERROR_OBJECT (self, "Incomplete caps"); return FALSE; } stream_format = gst_structure_get_string (s, "stream-format"); if (!stream_format) { GST_ERROR_OBJECT (self, "Incomplete caps"); return FALSE; } if (aac_param.nChannels != channels) return TRUE; if (aac_param.nSampleRate != rate) return TRUE; if (mpegversion == 2 && aac_param.eAACStreamFormat != OMX_AUDIO_AACStreamFormatMP2ADTS) return TRUE; if (aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatMP4ADTS && strcmp (stream_format, "adts") != 0) return TRUE; if (aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatMP4LOAS && strcmp (stream_format, "loas") != 0) return TRUE; if (aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatADIF && strcmp (stream_format, "adif") != 0) return TRUE; if (aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatRAW && strcmp (stream_format, "raw") != 0) return TRUE; return FALSE; }
static gboolean resample_set_state_from_caps (ResampleState * state, GstCaps * incaps, GstCaps * outcaps, gint * channels, gint * inrate, gint * outrate) { GstStructure *structure; gboolean ret; gint myinrate, myoutrate; int mychannels; gint width, depth; ResampleFormat format; GST_DEBUG ("incaps %" GST_PTR_FORMAT ", outcaps %" GST_PTR_FORMAT, incaps, outcaps); structure = gst_caps_get_structure (incaps, 0); /* get width */ ret = gst_structure_get_int (structure, "width", &width); if (!ret) goto no_width; /* figure out the format */ if (g_str_equal (gst_structure_get_name (structure), "audio/x-raw-float")) { if (width == 32) format = RESAMPLE_FORMAT_F32; else if (width == 64) format = RESAMPLE_FORMAT_F64; else goto wrong_depth; } else { /* for int, depth and width must be the same */ ret = gst_structure_get_int (structure, "depth", &depth); if (!ret || width != depth) goto not_equal; if (width == 16) format = RESAMPLE_FORMAT_S16; else if (width == 32) format = RESAMPLE_FORMAT_S32; else goto wrong_depth; } ret = gst_structure_get_int (structure, "rate", &myinrate); ret &= gst_structure_get_int (structure, "channels", &mychannels); if (!ret) goto no_in_rate_channels; structure = gst_caps_get_structure (outcaps, 0); ret = gst_structure_get_int (structure, "rate", &myoutrate); if (!ret) goto no_out_rate; if (channels) *channels = mychannels; if (inrate) *inrate = myinrate; if (outrate) *outrate = myoutrate; resample_set_format (state, format); resample_set_n_channels (state, mychannels); resample_set_input_rate (state, myinrate); resample_set_output_rate (state, myoutrate); return TRUE; /* ERRORS */ no_width: { GST_DEBUG ("failed to get width from caps"); return FALSE; } not_equal: { GST_DEBUG ("width %d and depth %d must be the same", width, depth); return FALSE; } wrong_depth: { GST_DEBUG ("unknown depth %d found", depth); return FALSE; } no_in_rate_channels: { GST_DEBUG ("could not get input rate and channels"); return FALSE; } no_out_rate: { GST_DEBUG ("could not get output rate"); return FALSE; } }
static gboolean gst_omx_aac_dec_set_format (GstOMXAudioDec * dec, GstOMXPort * port, GstCaps * caps) { GstOMXAACDec *self = GST_OMX_AAC_DEC (dec); OMX_PARAM_PORTDEFINITIONTYPE port_def; OMX_AUDIO_PARAM_AACPROFILETYPE aac_param; OMX_ERRORTYPE err; GstStructure *s; gint rate, channels, mpegversion; const gchar *stream_format; gst_omx_port_get_port_definition (port, &port_def); port_def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; err = gst_omx_port_update_port_definition (port, &port_def); if (err != OMX_ErrorNone) { GST_ERROR_OBJECT (self, "Failed to set AAC format on component: %s (0x%08x)", gst_omx_error_to_string (err), err); return FALSE; } GST_OMX_INIT_STRUCT (&aac_param); aac_param.nPortIndex = port->index; err = gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioAac, &aac_param); if (err != OMX_ErrorNone) { GST_ERROR_OBJECT (self, "Failed to get AAC parameters from component: %s (0x%08x)", gst_omx_error_to_string (err), err); return FALSE; } s = gst_caps_get_structure (caps, 0); if (!gst_structure_get_int (s, "mpegversion", &mpegversion) || !gst_structure_get_int (s, "rate", &rate) || !gst_structure_get_int (s, "channels", &channels)) { GST_ERROR_OBJECT (self, "Incomplete caps"); return FALSE; } stream_format = gst_structure_get_string (s, "stream-format"); if (!stream_format) { GST_ERROR_OBJECT (self, "Incomplete caps"); return FALSE; } aac_param.nChannels = channels; aac_param.nSampleRate = rate; aac_param.nBitRate = 0; /* unknown */ aac_param.nAudioBandWidth = 0; /* decoder decision */ aac_param.eChannelMode = 0; /* FIXME */ if (mpegversion == 2) aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP2ADTS; else if (strcmp (stream_format, "adts") == 0) aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS; else if (strcmp (stream_format, "loas") == 0) aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4LOAS; else if (strcmp (stream_format, "adif") == 0) aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatADIF; else if (strcmp (stream_format, "raw") == 0) aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatRAW; else /* fallback instead of failing */ aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatRAW; err = gst_omx_component_set_parameter (dec->dec, OMX_IndexParamAudioAac, &aac_param); if (err != OMX_ErrorNone) { GST_ERROR_OBJECT (self, "Error setting AAC parameters: %s (0x%08x)", gst_omx_error_to_string (err), err); return FALSE; } return TRUE; }
static gboolean gst_mpg123_audio_dec_set_format (GstAudioDecoder * dec, GstCaps * input_caps) { /* Using the parsed information upstream, and the list of allowed caps * downstream, this code tries to find a suitable audio info. It is important * to keep in mind that the rate and number of channels should never deviate * from the one the bitstream has, otherwise mpg123 has to mix channels and/or * resample (and as its docs say, its internal resampler is very crude). The * sample format, however, can be chosen freely, because the MPEG specs do not * mandate any special format. Therefore, rate and number of channels are taken * from upstream (which parsed the MPEG frames, so the input_caps contain * exactly the rate and number of channels the bitstream actually has), while * the sample format is chosen by trying out all caps that are allowed by * downstream. This way, the output is adjusted to what the downstream prefers. * * Also, the new output audio info is not set immediately. Instead, it is * considered the "next audioinfo". The code waits for mpg123 to notice the new * format (= when mpg123_decode_frame() returns MPG123_AUDIO_DEC_NEW_FORMAT), * and then sets the next audioinfo. Otherwise, the next audioinfo is set too * soon, which may cause problems with mp3s containing several format headers. * One example would be an mp3 with the first 30 seconds using 44.1 kHz, then * the next 30 seconds using 32 kHz. Rare, but possible. * * STEPS: * * 1. get rate and channels from input_caps * 2. get allowed caps from src pad * 3. for each structure in allowed caps: * 3.1. take format * 3.2. if the combination of format with rate and channels is unsupported by * mpg123, go to (3), or exit with error if there are no more structures * to try * 3.3. create next audioinfo out of rate,channels,format, and exit */ int rate, channels; GstMpg123AudioDec *mpg123_decoder; GstCaps *allowed_srccaps; guint structure_nr; gboolean match_found = FALSE; mpg123_decoder = GST_MPG123_AUDIO_DEC (dec); g_assert (mpg123_decoder->handle != NULL); mpg123_decoder->has_next_audioinfo = FALSE; /* Get rate and channels from input_caps */ { GstStructure *structure; gboolean err = FALSE; /* Only the first structure is used (multiple * input caps structures don't make sense */ structure = gst_caps_get_structure (input_caps, 0); if (!gst_structure_get_int (structure, "rate", &rate)) { err = TRUE; GST_ERROR_OBJECT (dec, "Input caps do not have a rate value"); } if (!gst_structure_get_int (structure, "channels", &channels)) { err = TRUE; GST_ERROR_OBJECT (dec, "Input caps do not have a channel value"); } if (err) return FALSE; } /* Get the caps that are allowed by downstream */ { GstCaps *allowed_srccaps_unnorm = gst_pad_get_allowed_caps (GST_AUDIO_DECODER_SRC_PAD (dec)); if (!allowed_srccaps_unnorm) { GST_ERROR_OBJECT (dec, "Allowed src caps are NULL"); return FALSE; } allowed_srccaps = gst_caps_normalize (allowed_srccaps_unnorm); } /* Go through all allowed caps, pick the first one that matches */ for (structure_nr = 0; structure_nr < gst_caps_get_size (allowed_srccaps); ++structure_nr) { GstStructure *structure; gchar const *format_str; GstAudioFormat format; int encoding; structure = gst_caps_get_structure (allowed_srccaps, structure_nr); format_str = gst_structure_get_string (structure, "format"); if (format_str == NULL) { GST_DEBUG_OBJECT (dec, "Could not get format from src caps"); continue; } format = gst_audio_format_from_string (format_str); if (format == GST_AUDIO_FORMAT_UNKNOWN) { GST_DEBUG_OBJECT (dec, "Unknown format %s", format_str); continue; } switch (format) { case GST_AUDIO_FORMAT_S16: encoding = MPG123_ENC_SIGNED_16; break; case GST_AUDIO_FORMAT_S24: encoding = MPG123_ENC_SIGNED_24; break; case GST_AUDIO_FORMAT_S32: encoding = MPG123_ENC_SIGNED_32; break; case GST_AUDIO_FORMAT_U16: encoding = MPG123_ENC_UNSIGNED_16; break; case GST_AUDIO_FORMAT_U24: encoding = MPG123_ENC_UNSIGNED_24; break; case GST_AUDIO_FORMAT_U32: encoding = MPG123_ENC_UNSIGNED_32; break; case GST_AUDIO_FORMAT_F32: encoding = MPG123_ENC_FLOAT_32; break; default: GST_DEBUG_OBJECT (dec, "Format %s in srccaps is not supported", format_str); continue; } { int err; /* Cleanup old formats & set new one */ mpg123_format_none (mpg123_decoder->handle); err = mpg123_format (mpg123_decoder->handle, rate, channels, encoding); if (err != MPG123_OK) { GST_DEBUG_OBJECT (dec, "mpg123 cannot use caps %" GST_PTR_FORMAT " because mpg123_format() failed: %s", structure, mpg123_strerror (mpg123_decoder->handle)); continue; } } gst_audio_info_init (&(mpg123_decoder->next_audioinfo)); gst_audio_info_set_format (&(mpg123_decoder->next_audioinfo), format, rate, channels, NULL); GST_LOG_OBJECT (dec, "The next audio format is: %s, %u Hz, %u channels", format_str, rate, channels); mpg123_decoder->has_next_audioinfo = TRUE; match_found = TRUE; break; } gst_caps_unref (allowed_srccaps); return match_found; }
static gboolean sink_setcaps(GstPad *pad, GstCaps *caps) { GstDspVEnc *self; GstDspBase *base; GstStructure *in_struc; GstCaps *out_caps; GstStructure *out_struc; gint width = 0, height = 0; GstCaps *allowed_caps; gint tgt_level = -1; struct td_codec *codec; self = GST_DSP_VENC(GST_PAD_PARENT(pad)); base = GST_DSP_BASE(self); codec = base->codec; if (!codec) return FALSE; #ifdef DEBUG { gchar *str = gst_caps_to_string(caps); pr_info(self, "sink caps: %s", str); g_free(str); } #endif in_struc = gst_caps_get_structure(caps, 0); out_caps = gst_caps_new_empty(); switch (base->alg) { case GSTDSP_JPEGENC: out_struc = gst_structure_new("image/jpeg", NULL); break; case GSTDSP_H263ENC: out_struc = gst_structure_new("video/x-h263", "variant", G_TYPE_STRING, "itu", NULL); break; case GSTDSP_MP4VENC: out_struc = gst_structure_new("video/mpeg", "mpegversion", G_TYPE_INT, 4, "systemstream", G_TYPE_BOOLEAN, FALSE, NULL); break; case GSTDSP_H264ENC: out_struc = gst_structure_new("video/x-h264", "alignment", G_TYPE_STRING, "au", NULL); break; default: return FALSE; } if (gst_structure_get_int(in_struc, "width", &width)) gst_structure_set(out_struc, "width", G_TYPE_INT, width, NULL); if (gst_structure_get_int(in_struc, "height", &height)) gst_structure_set(out_struc, "height", G_TYPE_INT, height, NULL); gst_structure_get_fourcc(in_struc, "format", &self->color_format); switch (base->alg) { case GSTDSP_H263ENC: case GSTDSP_MP4VENC: case GSTDSP_H264ENC: base->output_buffer_size = width * height / 2; break; case GSTDSP_JPEGENC: if (width % 2 || height % 2) return FALSE; if (self->color_format == GST_MAKE_FOURCC('I', '4', '2', '0')) base->input_buffer_size = ROUND_UP(width, 16) * ROUND_UP(height, 16) * 3 / 2; else base->input_buffer_size = ROUND_UP(width, 16) * ROUND_UP(height, 16) * 2; base->output_buffer_size = width * height; if (self->quality < 10) base->output_buffer_size /= 10; else if (self->quality < 100) base->output_buffer_size /= (100 / self->quality); break; default: break; } if (base->node) goto skip_setup; switch (base->alg) { case GSTDSP_JPEGENC: du_port_alloc_buffers(base->ports[0], 1); #if SN_API > 1 du_port_alloc_buffers(base->ports[1], 2); #else /* old versions of the sn can't handle 2 buffers */ /* * Some constrained pipelines might starve because of this. You * might want to try enable-last-buffer=false on some sinks. * TODO Is there any way around this? */ du_port_alloc_buffers(base->ports[1], 1); #endif break; default: du_port_alloc_buffers(base->ports[0], 2); du_port_alloc_buffers(base->ports[1], 4); break; } skip_setup: self->width = width; self->height = height; { const GValue *framerate = NULL; framerate = gst_structure_get_value(in_struc, "framerate"); if (framerate) { gst_structure_set_value(out_struc, "framerate", framerate); /* calculate nearest integer */ self->framerate = (gst_value_get_fraction_numerator(framerate) * 2 / gst_value_get_fraction_denominator(framerate) + 1) / 2; } } /* see if downstream caps express something */ allowed_caps = gst_pad_get_allowed_caps(base->srcpad); if (allowed_caps) { if (gst_caps_get_size(allowed_caps) > 0) { GstStructure *s; s = gst_caps_get_structure(allowed_caps, 0); gst_structure_get_int(s, "level", &tgt_level); if (base->alg == GSTDSP_H264ENC) { const char *stream_format; stream_format = gst_structure_get_string(s, "stream-format"); if (stream_format && !strcmp(stream_format, "avc")) self->priv.h264.bytestream = false; else stream_format = "byte-stream"; gst_structure_set(out_struc, "stream-format", G_TYPE_STRING, stream_format, NULL); } } gst_caps_unref(allowed_caps); } check_supported_levels(self, tgt_level); if (self->bitrate == 0) self->bitrate = self->max_bitrate; else if (self->bitrate > self->max_bitrate) self->bitrate = self->max_bitrate; gst_caps_append_structure(out_caps, out_struc); #ifdef DEBUG { gchar *str = gst_caps_to_string(out_caps); pr_info(self, "src caps: %s", str); g_free(str); } #endif if (!gst_pad_take_caps(base->srcpad, out_caps)) return FALSE; if (base->node) return TRUE; base->node = create_node(self); if (!base->node) { pr_err(self, "dsp node creation failed"); return FALSE; } if (codec->setup_params) codec->setup_params(base); if (!gstdsp_start(base)) { pr_err(self, "dsp start failed"); return FALSE; } if (codec->send_params) codec->send_params(base, base->node); return TRUE; }
GdkPixbuf * xplayer_gst_playbin_get_frame (GstElement *play) { GstStructure *s; GstSample *sample = NULL; GdkPixbuf *pixbuf = NULL; GstCaps *to_caps, *sample_caps; gint outwidth = 0; gint outheight = 0; GstMemory *memory; GstMapInfo info; GdkPixbufRotation rotation = GDK_PIXBUF_ROTATE_NONE; g_return_val_if_fail (play != NULL, NULL); g_return_val_if_fail (GST_IS_ELEMENT (play), NULL); /* our desired output format (RGB24) */ to_caps = gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING, "RGB", /* Note: we don't ask for a specific width/height here, so that * videoscale can adjust dimensions from a non-1/1 pixel aspect * ratio to a 1/1 pixel-aspect-ratio. We also don't ask for a * specific framerate, because the input framerate won't * necessarily match the output framerate if there's a deinterlacer * in the pipeline. */ "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL); /* get frame */ g_signal_emit_by_name (play, "convert-sample", to_caps, &sample); gst_caps_unref (to_caps); if (!sample) { GST_DEBUG ("Could not take screenshot: %s", "failed to retrieve or convert video frame"); g_warning ("Could not take screenshot: %s", "failed to retrieve or convert video frame"); return NULL; } sample_caps = gst_sample_get_caps (sample); if (!sample_caps) { GST_DEBUG ("Could not take screenshot: %s", "no caps on output buffer"); g_warning ("Could not take screenshot: %s", "no caps on output buffer"); return NULL; } GST_DEBUG ("frame caps: %" GST_PTR_FORMAT, sample_caps); s = gst_caps_get_structure (sample_caps, 0); gst_structure_get_int (s, "width", &outwidth); gst_structure_get_int (s, "height", &outheight); if (outwidth <= 0 || outheight <= 0) goto done; memory = gst_buffer_get_memory (gst_sample_get_buffer (sample), 0); gst_memory_map (memory, &info, GST_MAP_READ); /* create pixbuf from that - use our own destroy function */ pixbuf = gdk_pixbuf_new_from_data (info.data, GDK_COLORSPACE_RGB, FALSE, 8, outwidth, outheight, GST_ROUND_UP_4 (outwidth * 3), destroy_pixbuf, sample); gst_memory_unmap (memory, &info); done: if (!pixbuf) { GST_DEBUG ("Could not take screenshot: %s", "could not create pixbuf"); g_warning ("Could not take screenshot: %s", "could not create pixbuf"); gst_sample_unref (sample); } /* Did we check whether we need to rotate the video? */ if (g_object_get_data (G_OBJECT (play), "orientation-checked") == NULL) { GstTagList *tags = NULL; g_signal_emit_by_name (G_OBJECT (play), "get-video-tags", 0, &tags); if (tags) { char *orientation_str; gboolean ret; ret = gst_tag_list_get_string_index (tags, GST_TAG_IMAGE_ORIENTATION, 0, &orientation_str); if (!ret || !orientation_str) rotation = GDK_PIXBUF_ROTATE_NONE; else if (g_str_equal (orientation_str, "rotate-90")) rotation = GDK_PIXBUF_ROTATE_CLOCKWISE; else if (g_str_equal (orientation_str, "rotate-180")) rotation = GDK_PIXBUF_ROTATE_UPSIDEDOWN; else if (g_str_equal (orientation_str, "rotate-270")) rotation = GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE; gst_tag_list_unref (tags); } g_object_set_data (G_OBJECT (play), "orientation-checked", GINT_TO_POINTER(1)); g_object_set_data (G_OBJECT (play), "orientation", GINT_TO_POINTER(rotation)); } rotation = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (play), "orientation")); if (rotation != GDK_PIXBUF_ROTATE_NONE) { GdkPixbuf *rotated; rotated = gdk_pixbuf_rotate_simple (pixbuf, rotation); if (rotated) { g_object_unref (pixbuf); pixbuf = rotated; } } return pixbuf; }
static gboolean gst_divxenc_setcaps (GstPad * pad, GstCaps * caps) { GstDivxEnc *divxenc; GstStructure *structure = gst_caps_get_structure (caps, 0); gint w, h; const GValue *fps; guint32 fourcc; guint32 divx_cs; gint bitcnt = 0; gboolean ret = FALSE; divxenc = GST_DIVXENC (gst_pad_get_parent (pad)); /* if there's something old around, remove it */ gst_divxenc_unset (divxenc); gst_structure_get_int (structure, "width", &w); gst_structure_get_int (structure, "height", &h); gst_structure_get_fourcc (structure, "format", &fourcc); fps = gst_structure_get_value (structure, "framerate"); if (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps)) { divxenc->fps_n = gst_value_get_fraction_numerator (fps); divxenc->fps_d = gst_value_get_fraction_denominator (fps); } else { divxenc->fps_n = -1; } switch (fourcc) { case GST_MAKE_FOURCC ('I', '4', '2', '0'): divx_cs = GST_MAKE_FOURCC ('I', '4', '2', '0'); break; case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'): divx_cs = GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'); break; case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): divx_cs = GST_MAKE_FOURCC ('Y', 'V', '1', '2'); break; case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'): divx_cs = GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'); break; case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'): divx_cs = GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'); break; default: ret = FALSE; goto done; } divxenc->csp = divx_cs; divxenc->bitcnt = bitcnt; divxenc->width = w; divxenc->height = h; /* try it */ if (gst_divxenc_setup (divxenc)) { GstCaps *new_caps = NULL; new_caps = gst_caps_new_simple ("video/x-divx", "divxversion", G_TYPE_INT, 5, "width", G_TYPE_INT, w, "height", G_TYPE_INT, h, "framerate", GST_TYPE_FRACTION, divxenc->fps_n, divxenc->fps_d, NULL); if (new_caps) { if (!gst_pad_set_caps (divxenc->srcpad, new_caps)) { gst_divxenc_unset (divxenc); ret = FALSE; goto done; } gst_caps_unref (new_caps); ret = TRUE; goto done; } } /* if we got here - it's not good */ ret = FALSE; done: gst_object_unref (divxenc); return ret; }
int main(int argc, char** argv) { char *config = getenv("GSCAM_CONFIG"); if (config == NULL) { std::cout << "Problem getting GSCAM_CONFIG variable." << std::endl; exit(-1); } gst_init(0,0); std::cout << "Gstreamer Version: " << gst_version_string() << std::endl; GError *error = 0; //assignment to zero is a gst requirement GstElement *pipeline = gst_parse_launch(config,&error); if (pipeline == NULL) { std::cout << error->message << std::endl; exit(-1); } GstElement * sink = gst_element_factory_make("appsink",NULL); GstCaps * caps = gst_caps_new_simple("video/x-raw-rgb", NULL); gst_app_sink_set_caps(GST_APP_SINK(sink), caps); gst_caps_unref(caps); gst_base_sink_set_sync(GST_BASE_SINK(sink), TRUE); if(GST_IS_PIPELINE(pipeline)) { GstPad *outpad = gst_bin_find_unlinked_pad(GST_BIN(pipeline), GST_PAD_SRC); g_assert(outpad); GstElement *outelement = gst_pad_get_parent_element(outpad); g_assert(outelement); gst_object_unref(outpad); if(!gst_bin_add(GST_BIN(pipeline), sink)) { fprintf(stderr, "gst_bin_add() failed\n"); // TODO: do some unref gst_object_unref(outelement); gst_object_unref(pipeline); return -1; } if(!gst_element_link(outelement, sink)) { fprintf(stderr, "GStreamer: cannot link outelement(\"%s\") -> sink\n", gst_element_get_name(outelement)); gst_object_unref(outelement); gst_object_unref(pipeline); return -1; } gst_object_unref(outelement); } else { GstElement* launchpipe = pipeline; pipeline = gst_pipeline_new(NULL); g_assert(pipeline); gst_object_unparent(GST_OBJECT(launchpipe)); gst_bin_add_many(GST_BIN(pipeline), launchpipe, sink, NULL); if(!gst_element_link(launchpipe, sink)) { fprintf(stderr, "GStreamer: cannot link launchpipe -> sink\n"); gst_object_unref(pipeline); return -1; } } gst_element_set_state(pipeline, GST_STATE_PAUSED); if (gst_element_get_state(pipeline, NULL, NULL, -1) == GST_STATE_CHANGE_FAILURE) { std::cout << "Failed to PAUSE." << std::endl; exit(-1); } else { std::cout << "stream is PAUSED." << std::endl; } // We could probably do something with the camera name, check // errors or something, but at the moment, we don't care. std::string camera_name; if (camera_calibration_parsers::readCalibrationIni("../camera_parameters.txt", camera_name, camera_info)) { ROS_INFO("Successfully read camera calibration. Rerun camera calibrator if it is incorrect."); } else { ROS_ERROR("No camera_parameters.txt file found. Use default file if no other is available."); } ros::init(argc, argv, "gscam_publisher"); ros::NodeHandle nh; int preroll; nh.param("brown/gscam/preroll", preroll, 0); if (preroll) { //The PAUSE, PLAY, PAUSE, PLAY cycle is to ensure proper pre-roll //I am told this is needed and am erring on the side of caution. gst_element_set_state(pipeline, GST_STATE_PLAYING); if (gst_element_get_state(pipeline, NULL, NULL, -1) == GST_STATE_CHANGE_FAILURE) { std::cout << "Failed to PLAY." << std::endl; exit(-1); } else { std::cout << "stream is PLAYING." << std::endl; } gst_element_set_state(pipeline, GST_STATE_PAUSED); if (gst_element_get_state(pipeline, NULL, NULL, -1) == GST_STATE_CHANGE_FAILURE) { std::cout << "Failed to PAUSE." << std::endl; exit(-1); } else { std::cout << "stream is PAUSED." << std::endl; } } image_transport::ImageTransport it(nh); // image_transport::CameraPublisher pub = it.advertiseCamera("gscam/image_raw", 1); //------------------------------------ // Added by jschoi, 2012-08-13 char topic_name[32]; if(argc==1) sprintf(topic_name, "gscam/image_raw"); else sprintf(topic_name,"%s",argv[1]); // To get the name of topic from the first arguement //------------------------------------ image_transport::CameraPublisher pub = it.advertiseCamera(topic_name, 1); ros::ServiceServer set_camera_info = nh.advertiseService("gscam/set_camera_info", setCameraInfo); std::cout << "Processing..." << std::endl; //processVideo rosPad = false; gstreamerPad = true; gst_element_set_state(pipeline, GST_STATE_PLAYING); while(nh.ok()) { // This should block until a new frame is awake, this way, we'll run at the // actual capture framerate of the device. GstBuffer* buf = gst_app_sink_pull_buffer(GST_APP_SINK(sink)); if (!buf) break; GstPad* pad = gst_element_get_static_pad(sink, "sink"); const GstCaps *caps = gst_pad_get_negotiated_caps(pad); GstStructure *structure = gst_caps_get_structure(caps,0); gst_structure_get_int(structure,"width",&width); gst_structure_get_int(structure,"height",&height); sensor_msgs::Image msg; msg.width = width; msg.height = height; msg.encoding = "rgb8"; msg.is_bigendian = false; msg.step = width*3; msg.data.resize(width*height*3); std::copy(buf->data, buf->data+(width*height*3), msg.data.begin()); pub.publish(msg, camera_info); gst_buffer_unref(buf); ros::spinOnce(); } //close out std::cout << "\nquitting..." << std::endl; gst_element_set_state(pipeline, GST_STATE_NULL); gst_object_unref(pipeline); return 0; }
/* returns static descriptions and dynamic ones (such as video/x-raw), * or NULL if caps aren't known at all */ static gchar * format_info_get_desc (const FormatInfo * info, const GstCaps * caps) { const GstStructure *s; g_assert (info != NULL); if (info->desc != NULL) return g_strdup (_(info->desc)); s = gst_caps_get_structure (caps, 0); if (strcmp (info->type, "video/x-raw") == 0) { gchar *ret = NULL; const gchar *str = 0; GstVideoFormat format; const GstVideoFormatInfo *finfo; str = gst_structure_get_string (s, "format"); if (str == NULL) return g_strdup (_("Uncompressed video")); format = gst_video_format_from_string (str); if (format == GST_VIDEO_FORMAT_UNKNOWN) return g_strdup (_("Uncompressed video")); finfo = gst_video_format_get_info (format); if (GST_VIDEO_FORMAT_INFO_IS_GRAY (finfo)) { ret = g_strdup (_("Uncompressed gray")); } else if (GST_VIDEO_FORMAT_INFO_IS_YUV (finfo)) { const gchar *layout; const gchar *subs; gint w_sub, h_sub; w_sub = GST_VIDEO_FORMAT_INFO_W_SUB (finfo, 1); h_sub = GST_VIDEO_FORMAT_INFO_H_SUB (finfo, 1); if (GST_VIDEO_FORMAT_INFO_N_PLANES (finfo) == 1) { layout = "planar"; } else { layout = "packed"; } if (w_sub == 1 && h_sub == 1) { subs = "4:4:4"; } else if (w_sub == 2 && h_sub == 1) { subs = "4:2:2"; } else if (w_sub == 2 && h_sub == 2) { subs = "4:2:0"; } else if (w_sub == 4 && h_sub == 1) { subs = "4:1:1"; } else { subs = ""; } ret = g_strdup_printf (_("Uncompressed %s YUV %s"), layout, subs); } else if (GST_VIDEO_FORMAT_INFO_IS_RGB (finfo)) { gboolean alpha, palette; gint bits; alpha = GST_VIDEO_FORMAT_INFO_HAS_ALPHA (finfo); palette = GST_VIDEO_FORMAT_INFO_HAS_PALETTE (finfo); bits = GST_VIDEO_FORMAT_INFO_BITS (finfo); ret = g_strdup_printf (_("Uncompressed %s%d-bit %s"), palette ? "palettized " : "", bits, alpha ? "RGBA" : "RGB"); } else { ret = g_strdup (_("Uncompressed video")); } return ret; } else if (strcmp (info->type, "video/x-h263") == 0) { const gchar *variant, *ret; variant = gst_structure_get_string (s, "variant"); if (variant == NULL) ret = "H.263"; else if (strcmp (variant, "itu") == 0) ret = "ITU H.26n"; /* why not ITU H.263? (tpm) */ else if (strcmp (variant, "lead") == 0) ret = "Lead H.263"; else if (strcmp (variant, "microsoft") == 0) ret = "Microsoft H.263"; else if (strcmp (variant, "vdolive") == 0) ret = "VDOLive"; else if (strcmp (variant, "vivo") == 0) ret = "Vivo H.263"; else if (strcmp (variant, "xirlink") == 0) ret = "Xirlink H.263"; else { GST_WARNING ("Unknown H263 variant '%s'", variant); ret = "H.263"; } return g_strdup (ret); } else if (strcmp (info->type, "video/x-h264") == 0) { const gchar *variant, *ret; variant = gst_structure_get_string (s, "variant"); if (variant == NULL) ret = "H.264"; else if (strcmp (variant, "itu") == 0) ret = "ITU H.264"; else if (strcmp (variant, "videosoft") == 0) ret = "Videosoft H.264"; else if (strcmp (variant, "lead") == 0) ret = "Lead H.264"; else { GST_WARNING ("Unknown H264 variant '%s'", variant); ret = "H.264"; } return g_strdup (ret); } else if (strcmp (info->type, "video/x-divx") == 0) { gint ver = 0; if (!gst_structure_get_int (s, "divxversion", &ver) || ver <= 2) { GST_WARNING ("Unexpected DivX version in %" GST_PTR_FORMAT, caps); return g_strdup ("DivX MPEG-4"); } return g_strdup_printf (_("DivX MPEG-4 Version %d"), ver); } else if (strcmp (info->type, "video/x-msmpeg") == 0) { gint ver = 0; if (!gst_structure_get_int (s, "msmpegversion", &ver) || ver < 40 || ver > 49) { GST_WARNING ("Unexpected msmpegversion in %" GST_PTR_FORMAT, caps); return g_strdup ("Microsoft MPEG-4 4.x"); } return g_strdup_printf ("Microsoft MPEG-4 4.%d", ver % 10); } else if (strcmp (info->type, "video/x-truemotion") == 0) { gint ver = 0; gst_structure_get_int (s, "trueversion", &ver); switch (ver) { case 1: return g_strdup_printf ("Duck TrueMotion 1"); case 2: return g_strdup_printf ("TrueMotion 2.0"); default: GST_WARNING ("Unexpected trueversion in %" GST_PTR_FORMAT, caps); break; } return g_strdup_printf ("TrueMotion"); } else if (strcmp (info->type, "video/x-xan") == 0) { gint ver = 0; if (!gst_structure_get_int (s, "wcversion", &ver) || ver < 1) { GST_WARNING ("Unexpected wcversion in %" GST_PTR_FORMAT, caps); return g_strdup ("Xan Wing Commander"); } return g_strdup_printf ("Xan Wing Commander %u", ver); } else if (strcmp (info->type, "video/x-indeo") == 0) { gint ver = 0; if (!gst_structure_get_int (s, "indeoversion", &ver) || ver < 2) { GST_WARNING ("Unexpected indeoversion in %" GST_PTR_FORMAT, caps); return g_strdup ("Intel Indeo"); } return g_strdup_printf ("Intel Indeo %u", ver); } else if (strcmp (info->type, "audio/x-wma") == 0) { gint ver = 0; gst_structure_get_int (s, "wmaversion", &ver); switch (ver) { case 1: case 2: case 3: return g_strdup_printf ("Windows Media Audio %d", ver + 6); default: break; } GST_WARNING ("Unexpected wmaversion in %" GST_PTR_FORMAT, caps); return g_strdup ("Windows Media Audio"); } else if (strcmp (info->type, "video/x-wmv") == 0) { gint ver = 0; gst_structure_get_int (s, "wmvversion", &ver); switch (ver) { case 1: case 2: case 3: return g_strdup_printf ("Windows Media Video %d", ver + 6); default: break; } GST_WARNING ("Unexpected wmvversion in %" GST_PTR_FORMAT, caps); return g_strdup ("Windows Media Video"); } else if (strcmp (info->type, "audio/x-mace") == 0) { gint ver = 0; gst_structure_get_int (s, "maceversion", &ver); if (ver == 3 || ver == 6) { return g_strdup_printf ("MACE-%d", ver); } else { GST_WARNING ("Unexpected maceversion in %" GST_PTR_FORMAT, caps); return g_strdup ("MACE"); } } else if (strcmp (info->type, "video/x-svq") == 0) { gint ver = 0; gst_structure_get_int (s, "svqversion", &ver); if (ver == 1 || ver == 3) { return g_strdup_printf ("Sorensen Video %d", ver); } else { GST_WARNING ("Unexpected svqversion in %" GST_PTR_FORMAT, caps); return g_strdup ("Sorensen Video"); } } else if (strcmp (info->type, "video/x-asus") == 0) { gint ver = 0; gst_structure_get_int (s, "asusversion", &ver); if (ver == 1 || ver == 2) { return g_strdup_printf ("Asus Video %d", ver); } else { GST_WARNING ("Unexpected asusversion in %" GST_PTR_FORMAT, caps); return g_strdup ("Asus Video"); } } else if (strcmp (info->type, "video/x-ati-vcr") == 0) { gint ver = 0; gst_structure_get_int (s, "vcrversion", &ver); if (ver == 1 || ver == 2) { return g_strdup_printf ("ATI VCR %d", ver); } else { GST_WARNING ("Unexpected acrversion in %" GST_PTR_FORMAT, caps); return g_strdup ("ATI VCR"); } } else if (strcmp (info->type, "audio/x-adpcm") == 0) { const GValue *layout_val; layout_val = gst_structure_get_value (s, "layout"); if (layout_val != NULL && G_VALUE_HOLDS_STRING (layout_val)) { const gchar *layout; if ((layout = g_value_get_string (layout_val))) { gchar *layout_upper, *ret; if (strcmp (layout, "swf") == 0) return g_strdup ("Shockwave ADPCM"); if (strcmp (layout, "microsoft") == 0) return g_strdup ("Microsoft ADPCM"); if (strcmp (layout, "quicktime") == 0) return g_strdup ("Quicktime ADPCM"); if (strcmp (layout, "westwood") == 0) return g_strdup ("Westwood ADPCM"); if (strcmp (layout, "yamaha") == 0) return g_strdup ("Yamaha ADPCM"); /* FIXME: other layouts: sbpro2, sbpro3, sbpro4, ct, g726, ea, * adx, xa, 4xm, smjpeg, dk4, dk3, dvi */ layout_upper = g_ascii_strup (layout, -1); ret = g_strdup_printf ("%s ADPCM", layout_upper); g_free (layout_upper); return ret; } } return g_strdup ("ADPCM"); } else if (strcmp (info->type, "audio/mpeg") == 0) { gint ver = 0, layer = 0; gst_structure_get_int (s, "mpegversion", &ver); switch (ver) { case 1: gst_structure_get_int (s, "layer", &layer); switch (layer) { case 1: case 2: case 3: return g_strdup_printf ("MPEG-1 Layer %d (MP%d)", layer, layer); default: break; } GST_WARNING ("Unexpected MPEG-1 layer in %" GST_PTR_FORMAT, caps); return g_strdup ("MPEG-1 Audio"); case 4: return g_strdup ("MPEG-4 AAC"); default: break; } GST_WARNING ("Unexpected audio mpegversion in %" GST_PTR_FORMAT, caps); return g_strdup ("MPEG Audio"); } else if (strcmp (info->type, "audio/x-pn-realaudio") == 0) { gint ver = 0; gst_structure_get_int (s, "raversion", &ver); switch (ver) { case 1: return g_strdup ("RealAudio 14k4bps"); case 2: return g_strdup ("RealAudio 28k8bps"); case 8: return g_strdup ("RealAudio G2 (Cook)"); default: break; } GST_WARNING ("Unexpected raversion in %" GST_PTR_FORMAT, caps); return g_strdup ("RealAudio"); } else if (strcmp (info->type, "video/x-pn-realvideo") == 0) { gint ver = 0; gst_structure_get_int (s, "rmversion", &ver); switch (ver) { case 1: return g_strdup ("RealVideo 1.0"); case 2: return g_strdup ("RealVideo 2.0"); case 3: return g_strdup ("RealVideo 3.0"); case 4: return g_strdup ("RealVideo 4.0"); default: break; } GST_WARNING ("Unexpected rmversion in %" GST_PTR_FORMAT, caps); return g_strdup ("RealVideo"); } else if (strcmp (info->type, "video/mpeg") == 0) { gboolean sysstream; gint ver = 0; if (!gst_structure_get_boolean (s, "systemstream", &sysstream) || !gst_structure_get_int (s, "mpegversion", &ver) || ver < 1 || ver > 4) { GST_WARNING ("Missing fields in mpeg video caps %" GST_PTR_FORMAT, caps); } else { if (sysstream) { return g_strdup_printf ("MPEG-%d System Stream", ver); } else { return g_strdup_printf ("MPEG-%d Video", ver); } } return g_strdup ("MPEG Video"); } else if (strcmp (info->type, "audio/x-raw") == 0) { gint depth = 0; gboolean is_float; const gchar *str; GstAudioFormat format; const GstAudioFormatInfo *finfo; str = gst_structure_get_string (s, "format"); format = gst_audio_format_from_string (str); if (format == GST_AUDIO_FORMAT_UNKNOWN) return g_strdup (_("Uncompressed audio")); finfo = gst_audio_format_get_info (format); depth = GST_AUDIO_FORMAT_INFO_DEPTH (finfo); is_float = GST_AUDIO_FORMAT_INFO_IS_FLOAT (finfo); return g_strdup_printf (_("Raw %d-bit %s audio"), depth, is_float ? "floating-point" : "PCM"); } return NULL; }
gint gst_xvid_structure_to_csp (GstStructure * structure) { const gchar *mime = gst_structure_get_name (structure); gint xvid_cs = -1; if (!strcmp (mime, "video/x-raw-yuv")) { guint32 fourcc; gst_structure_get_fourcc (structure, "format", &fourcc); switch (fourcc) { case GST_MAKE_FOURCC ('I', '4', '2', '0'): xvid_cs = XVID_CSP_I420; break; case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'): xvid_cs = XVID_CSP_YUY2; break; case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): xvid_cs = XVID_CSP_YV12; break; case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'): xvid_cs = XVID_CSP_UYVY; break; case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'): xvid_cs = XVID_CSP_YVYU; break; } } else { gint depth, bpp, r_mask; gst_structure_get_int (structure, "depth", &depth); gst_structure_get_int (structure, "bpp", &bpp); gst_structure_get_int (structure, "red_mask", &r_mask); switch (depth) { case 15: xvid_cs = XVID_CSP_RGB555; break; case 16: xvid_cs = XVID_CSP_RGB565; break; case 24: if (bpp == 24) { xvid_cs = XVID_CSP_BGR; } else { switch (r_mask) { case 0xff000000: xvid_cs = XVID_CSP_RGBA; break; #ifdef XVID_CSP_ARGB case 0x00ff0000: xvid_cs = XVID_CSP_ARGB; break; #endif case 0x0000ff00: xvid_cs = XVID_CSP_BGRA; break; case 0x000000ff: xvid_cs = XVID_CSP_ABGR; break; } } break; default: break; } } return xvid_cs; }
static gboolean sink_setcaps(GstPad *pad, GstCaps *caps) { struct obj *self; GstStructure *in_struc; const char *name; int codec_id; const GValue *codec_data; GstBuffer *buf; AVCodecContext *ctx; self = (struct obj *)((GstObject *)pad)->parent; ctx = self->av_ctx; if (ctx) { /* reset */ get_delayed(self); gst_av_codec_close(ctx); av_freep(&ctx->extradata); av_freep(&self->av_ctx); self->initialized = false; } in_struc = gst_caps_get_structure(caps, 0); name = gst_structure_get_name(in_struc); if (strcmp(name, "video/x-h263") == 0) codec_id = CODEC_ID_H263; else if (strcmp(name, "video/x-h264") == 0) codec_id = CODEC_ID_H264; else if (strcmp(name, "video/mpeg") == 0) { int version; gst_structure_get_int(in_struc, "mpegversion", &version); switch (version) { case 4: codec_id = CODEC_ID_MPEG4; break; case 2: codec_id = CODEC_ID_MPEG2VIDEO; break; case 1: codec_id = CODEC_ID_MPEG1VIDEO; break; default: codec_id = CODEC_ID_NONE; break; } } else if (strcmp(name, "video/x-divx") == 0) { int version; gst_structure_get_int(in_struc, "divxversion", &version); switch (version) { case 5: case 4: codec_id = CODEC_ID_MPEG4; break; case 3: codec_id = CODEC_ID_MSMPEG4V3; break; default: codec_id = CODEC_ID_NONE; break; } } else if (strcmp(name, "video/x-xvid") == 0) codec_id = CODEC_ID_MPEG4; else if (strcmp(name, "video/x-3ivx") == 0) codec_id = CODEC_ID_MPEG4; else if (strcmp(name, "video/x-vp8") == 0) codec_id = CODEC_ID_VP8; else if (strcmp(name, "video/x-theora") == 0) codec_id = CODEC_ID_THEORA; else if (strcmp(name, "video/x-wmv") == 0) { int version; gst_structure_get_int(in_struc, "wmvversion", &version); switch (version) { case 3: { guint32 fourcc; codec_id = CODEC_ID_WMV3; if (gst_structure_get_fourcc(in_struc, "fourcc", &fourcc) || gst_structure_get_fourcc(in_struc, "format", &fourcc)) { if (fourcc == GST_MAKE_FOURCC('W', 'V', 'C', '1')) codec_id = CODEC_ID_VC1; } break; } case 2: codec_id = CODEC_ID_WMV2; break; case 1: codec_id = CODEC_ID_WMV1; break; default: codec_id = CODEC_ID_NONE; break; } } else codec_id = CODEC_ID_NONE; self->codec = avcodec_find_decoder(codec_id); if (!self->codec) return false; switch (codec_id) { case CODEC_ID_H263: self->parse_func = gst_av_h263_parse; break; case CODEC_ID_H264: self->parse_func = gst_av_h264_parse; break; case CODEC_ID_MPEG4: self->parse_func = gst_av_mpeg4_parse; break; } self->av_ctx = ctx = avcodec_alloc_context3(self->codec); ctx->get_buffer = get_buffer; ctx->release_buffer = release_buffer; ctx->reget_buffer = reget_buffer; ctx->opaque = self; ctx->flags |= CODEC_FLAG_EMU_EDGE; gst_structure_get_int(in_struc, "width", &ctx->width); gst_structure_get_int(in_struc, "height", &ctx->height); gst_structure_get_fraction(in_struc, "pixel-aspect-ratio", &ctx->sample_aspect_ratio.num, &ctx->sample_aspect_ratio.den); gst_structure_get_fraction(in_struc, "framerate", &ctx->time_base.den, &ctx->time_base.num); /* bug in xvimagesink? */ if (!ctx->time_base.num) ctx->time_base = (AVRational){ 1, 0 }; if (codec_id == CODEC_ID_THEORA) { get_theora_extradata(ctx, in_struc); goto next; } codec_data = gst_structure_get_value(in_struc, "codec_data"); if (!codec_data) goto next; buf = gst_value_get_buffer(codec_data); if (!buf) goto next; ctx->extradata = av_malloc(buf->size + FF_INPUT_BUFFER_PADDING_SIZE); memcpy(ctx->extradata, buf->data, buf->size); memset(ctx->extradata + buf->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); ctx->extradata_size = buf->size; if (self->parse_func) self->parse_func(self, buf); next: return true; }
static gboolean gst_rtp_L16_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps) { GstStructure *structure; GstRtpL16Depay *rtpL16depay; gint clock_rate, payload; gint channels; GstCaps *srccaps; gboolean res; const gchar *channel_order; const GstRTPChannelOrder *order; GstAudioInfo *info; rtpL16depay = GST_RTP_L16_DEPAY (depayload); structure = gst_caps_get_structure (caps, 0); payload = 96; gst_structure_get_int (structure, "payload", &payload); switch (payload) { case GST_RTP_PAYLOAD_L16_STEREO: channels = 2; clock_rate = 44100; break; case GST_RTP_PAYLOAD_L16_MONO: channels = 1; clock_rate = 44100; break; default: /* no fixed mapping, we need clock-rate */ channels = 0; clock_rate = 0; break; } /* caps can overwrite defaults */ clock_rate = gst_rtp_L16_depay_parse_int (structure, "clock-rate", clock_rate); if (clock_rate == 0) goto no_clockrate; channels = gst_rtp_L16_depay_parse_int (structure, "encoding-params", channels); if (channels == 0) { channels = gst_rtp_L16_depay_parse_int (structure, "channels", channels); if (channels == 0) { /* channels defaults to 1 otherwise */ channels = 1; } } depayload->clock_rate = clock_rate; info = &rtpL16depay->info; gst_audio_info_init (info); info->finfo = gst_audio_format_get_info (GST_AUDIO_FORMAT_S16BE); info->rate = clock_rate; info->channels = channels; info->bpf = (info->finfo->width / 8) * channels; /* add channel positions */ channel_order = gst_structure_get_string (structure, "channel-order"); order = gst_rtp_channels_get_by_order (channels, channel_order); rtpL16depay->order = order; if (order) { memcpy (info->position, order->pos, sizeof (GstAudioChannelPosition) * channels); gst_audio_channel_positions_to_valid_order (info->position, info->channels); } else { GST_ELEMENT_WARNING (rtpL16depay, STREAM, DECODE, (NULL), ("Unknown channel order '%s' for %d channels", GST_STR_NULL (channel_order), channels)); /* create default NONE layout */ gst_rtp_channels_create_default (channels, info->position); } srccaps = gst_audio_info_to_caps (info); res = gst_pad_set_caps (depayload->srcpad, srccaps); gst_caps_unref (srccaps); return res; /* ERRORS */ no_clockrate: { GST_ERROR_OBJECT (depayload, "no clock-rate specified"); return FALSE; } }
static gboolean gst_dshowvideodec_sink_setcaps (GstPad * pad, GstCaps * caps) { gboolean ret = FALSE; HRESULT hres; GstStructure *s = gst_caps_get_structure (caps, 0); GstDshowVideoDec *vdec = (GstDshowVideoDec *) gst_pad_get_parent (pad); GstDshowVideoDecClass *klass = (GstDshowVideoDecClass *) G_OBJECT_GET_CLASS (vdec); GstBuffer *extradata = NULL; const GValue *v = NULL; guint size = 0; GstCaps *caps_out; AM_MEDIA_TYPE output_mediatype, input_mediatype; VIDEOINFOHEADER *input_vheader = NULL, *output_vheader = NULL; CComPtr<IPin> output_pin; CComPtr<IPin> input_pin; IBaseFilter *srcfilter = NULL; IBaseFilter *sinkfilter = NULL; const GValue *fps, *par; /* read data */ if (!gst_structure_get_int (s, "width", &vdec->width) || !gst_structure_get_int (s, "height", &vdec->height)) { GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION, ("error getting video width or height from caps"), (NULL)); goto end; } fps = gst_structure_get_value (s, "framerate"); if (fps) { vdec->fps_n = gst_value_get_fraction_numerator (fps); vdec->fps_d = gst_value_get_fraction_denominator (fps); } else { /* Invent a sane default framerate; the timestamps matter * more anyway. */ vdec->fps_n = 25; vdec->fps_d = 1; } par = gst_structure_get_value (s, "pixel-aspect-ratio"); if (par) { vdec->par_n = gst_value_get_fraction_numerator (par); vdec->par_d = gst_value_get_fraction_denominator (par); } else { vdec->par_n = vdec->par_d = 1; } if ((v = gst_structure_get_value (s, "codec_data"))) extradata = gst_value_get_buffer (v); /* define the input type format */ memset (&input_mediatype, 0, sizeof (AM_MEDIA_TYPE)); input_mediatype.majortype = klass->entry->input_majortype; input_mediatype.subtype = klass->entry->input_subtype; input_mediatype.bFixedSizeSamples = FALSE; input_mediatype.bTemporalCompression = TRUE; if (strstr (klass->entry->sinkcaps, "video/mpeg, mpegversion= (int) 1")) { size = sizeof (MPEG1VIDEOINFO) + (extradata ? GST_BUFFER_SIZE (extradata) - 1 : 0); input_vheader = (VIDEOINFOHEADER *)g_malloc0 (size); input_vheader->bmiHeader.biSize = sizeof (BITMAPINFOHEADER); if (extradata) { MPEG1VIDEOINFO *mpeg_info = (MPEG1VIDEOINFO *) input_vheader; memcpy (mpeg_info->bSequenceHeader, GST_BUFFER_DATA (extradata), GST_BUFFER_SIZE (extradata)); mpeg_info->cbSequenceHeader = GST_BUFFER_SIZE (extradata); } input_mediatype.formattype = FORMAT_MPEGVideo; } else { size = sizeof (VIDEOINFOHEADER) + (extradata ? GST_BUFFER_SIZE (extradata) : 0); input_vheader = (VIDEOINFOHEADER *)g_malloc0 (size); input_vheader->bmiHeader.biSize = sizeof (BITMAPINFOHEADER); if (extradata) { /* Codec data is appended after our header */ memcpy (((guchar *) input_vheader) + sizeof (VIDEOINFOHEADER), GST_BUFFER_DATA (extradata), GST_BUFFER_SIZE (extradata)); input_vheader->bmiHeader.biSize += GST_BUFFER_SIZE (extradata); } input_mediatype.formattype = FORMAT_VideoInfo; } input_vheader->rcSource.top = input_vheader->rcSource.left = 0; input_vheader->rcSource.right = vdec->width; input_vheader->rcSource.bottom = vdec->height; input_vheader->rcTarget = input_vheader->rcSource; input_vheader->bmiHeader.biWidth = vdec->width; input_vheader->bmiHeader.biHeight = vdec->height; input_vheader->bmiHeader.biPlanes = 1; input_vheader->bmiHeader.biBitCount = 16; input_vheader->bmiHeader.biCompression = klass->entry->format; input_vheader->bmiHeader.biSizeImage = (vdec->width * vdec->height) * (input_vheader->bmiHeader.biBitCount / 8); input_mediatype.cbFormat = size; input_mediatype.pbFormat = (BYTE *) input_vheader; input_mediatype.lSampleSize = input_vheader->bmiHeader.biSizeImage; vdec->fakesrc->GetOutputPin()->SetMediaType(&input_mediatype); /* set the sample size for fakesrc filter to the output buffer size */ vdec->fakesrc->GetOutputPin()->SetSampleSize(input_mediatype.lSampleSize); /* connect our fake src to decoder */ hres = vdec->fakesrc->QueryInterface(IID_IBaseFilter, (void **) &srcfilter); if (FAILED (hres)) { GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION, ("Can't QT fakesrc to IBaseFilter: %x", hres), (NULL)); goto end; } output_pin = gst_dshow_get_pin_from_filter (srcfilter, PINDIR_OUTPUT); if (!output_pin) { GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION, ("Can't get output pin from our directshow fakesrc filter"), (NULL)); goto end; } input_pin = gst_dshow_get_pin_from_filter (vdec->decfilter, PINDIR_INPUT); if (!input_pin) { GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION, ("Can't get input pin from decoder filter"), (NULL)); goto end; } hres = vdec->filtergraph->ConnectDirect (output_pin, input_pin, NULL); if (hres != S_OK) { GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION, ("Can't connect fakesrc with decoder (error=%x)", hres), (NULL)); goto end; } /* get decoder output video format */ if (!gst_dshowvideodec_get_filter_output_format (vdec, klass->entry->output_subtype, &output_vheader, &size)) { GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION, ("Can't get decoder output video format"), (NULL)); goto end; } memset (&output_mediatype, 0, sizeof (AM_MEDIA_TYPE)); output_mediatype.majortype = klass->entry->output_majortype; output_mediatype.subtype = klass->entry->output_subtype; output_mediatype.bFixedSizeSamples = TRUE; output_mediatype.bTemporalCompression = FALSE; output_mediatype.lSampleSize = output_vheader->bmiHeader.biSizeImage; output_mediatype.formattype = FORMAT_VideoInfo; output_mediatype.cbFormat = size; output_mediatype.pbFormat = (BYTE *) output_vheader; vdec->fakesink->SetMediaType (&output_mediatype); /* connect decoder to our fake sink */ output_pin = gst_dshow_get_pin_from_filter (vdec->decfilter, PINDIR_OUTPUT); if (!output_pin) { GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION, ("Can't get output pin from our decoder filter"), (NULL)); goto end; } hres = vdec->fakesink->QueryInterface(IID_IBaseFilter, (void **) &sinkfilter); if (FAILED (hres)) { GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION, ("Can't QT fakesink to IBaseFilter: %x", hres), (NULL)); goto end; } input_pin = gst_dshow_get_pin_from_filter (sinkfilter, PINDIR_INPUT); if (!input_pin) { GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION, ("Can't get input pin from our directshow fakesink filter"), (NULL)); goto end; } hres = vdec->filtergraph->ConnectDirect(output_pin, input_pin, &output_mediatype); if (hres != S_OK) { GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION, ("Can't connect decoder with fakesink (error=%x)", hres), (NULL)); goto end; } /* negotiate output */ caps_out = gst_caps_from_string (klass->entry->srccaps); gst_caps_set_simple (caps_out, "width", G_TYPE_INT, vdec->width, "height", G_TYPE_INT, vdec->height, NULL); if (vdec->fps_n && vdec->fps_d) { gst_caps_set_simple (caps_out, "framerate", GST_TYPE_FRACTION, vdec->fps_n, vdec->fps_d, NULL); } gst_caps_set_simple (caps_out, "pixel-aspect-ratio", GST_TYPE_FRACTION, vdec->par_n, vdec->par_d, NULL); if (!gst_pad_set_caps (vdec->srcpad, caps_out)) { gst_caps_unref (caps_out); GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION, ("Failed to negotiate output"), (NULL)); goto end; } gst_caps_unref (caps_out); hres = vdec->mediafilter->Run (-1); if (hres != S_OK) { GST_ELEMENT_ERROR (vdec, CORE, NEGOTIATION, ("Can't run the directshow graph (error=%d)", hres), (NULL)); goto end; } ret = TRUE; end: gst_object_unref (vdec); if (input_vheader) g_free (input_vheader); if (srcfilter) srcfilter->Release(); if (sinkfilter) sinkfilter->Release(); return ret; }
static gboolean gst_kate_enc_sink_event (GstPad * pad, GstEvent * event) { GstKateEnc *ke = GST_KATE_ENC (gst_pad_get_parent (pad)); GstStructure *structure; gboolean ret; switch (GST_EVENT_TYPE (event)) { case GST_EVENT_NEWSEGMENT: GST_LOG_OBJECT (ke, "Got newsegment event"); if (ke->initialized) { GST_LOG_OBJECT (ke, "ensuring all headers are in"); if (gst_kate_enc_flush_headers (ke) != GST_FLOW_OK) { GST_WARNING_OBJECT (ke, "Failed to flush headers"); } else { GstFormat format; gint64 timestamp; gst_event_parse_new_segment (event, NULL, NULL, &format, ×tamp, NULL, NULL); if (format != GST_FORMAT_TIME || !GST_CLOCK_TIME_IS_VALID (timestamp)) { GST_WARNING_OBJECT (ke, "No time in newsegment event %p, format %d, timestamp %" G_GINT64_FORMAT, event, (int) format, timestamp); /* to be safe, we'd need to generate a keepalive anyway, but we'd have to guess at the timestamp to use; a good guess would be the last known timestamp plus the keepalive time, but if we then get a packet with a timestamp less than this, it would fail to encode, which would be Bad. If we don't encode a keepalive, we run the risk of stalling the pipeline and hanging, which is Very Bad. Oh dear. We can't exit(-1), can we ? */ } else { float t = timestamp / (double) GST_SECOND; if (ke->delayed_spu && t - ke->delayed_start / (double) GST_SECOND >= ke->default_spu_duration) { if (G_UNLIKELY (gst_kate_enc_flush_waiting (ke, timestamp) != GST_FLOW_OK)) { GST_WARNING_OBJECT (ke, "Failed to encode delayed packet"); /* continue with new segment handling anyway */ } } GST_LOG_OBJECT (ke, "ts %f, last %f (min %f)", t, ke->last_timestamp / (double) GST_SECOND, ke->keepalive_min_time); if (ke->keepalive_min_time > 0.0f && t - ke->last_timestamp / (double) GST_SECOND >= ke->keepalive_min_time) { /* we only generate a keepalive if there is no SPU waiting, as it would mean out of sequence start times - and granulepos */ if (!ke->delayed_spu) { gst_kate_enc_generate_keepalive (ke, timestamp); } } } } } ret = gst_pad_push_event (ke->srcpad, event); break; case GST_EVENT_CUSTOM_DOWNSTREAM: GST_LOG_OBJECT (ke, "Got custom downstream event"); /* adapted from the dvdsubdec element */ structure = event->structure; if (structure != NULL && gst_structure_has_name (structure, "application/x-gst-dvd")) { if (ke->initialized) { GST_LOG_OBJECT (ke, "ensuring all headers are in"); if (gst_kate_enc_flush_headers (ke) != GST_FLOW_OK) { GST_WARNING_OBJECT (ke, "Failed to flush headers"); } else { const gchar *event_name = gst_structure_get_string (structure, "event"); if (event_name) { if (!strcmp (event_name, "dvd-spu-clut-change")) { gchar name[16]; int idx; gboolean found; gint value; GST_INFO_OBJECT (ke, "New CLUT received"); for (idx = 0; idx < 16; ++idx) { g_snprintf (name, sizeof (name), "clut%02d", idx); found = gst_structure_get_int (structure, name, &value); if (found) { ke->spu_clut[idx] = value; } else { GST_WARNING_OBJECT (ke, "DVD CLUT event did not contain %s field", name); } } } else if (!strcmp (event_name, "dvd-lang-codes")) { /* we can't know which stream corresponds to us */ } } else { GST_WARNING_OBJECT (ke, "custom downstream event with no name"); } } } } ret = gst_pad_push_event (ke->srcpad, event); break; case GST_EVENT_TAG: GST_LOG_OBJECT (ke, "Got tag event"); if (ke->tags) { GstTagList *list; gst_event_parse_tag (event, &list); gst_tag_list_insert (ke->tags, list, gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (ke))); } else { g_assert_not_reached (); } ret = gst_pad_event_default (pad, event); break; case GST_EVENT_EOS: GST_INFO_OBJECT (ke, "Got EOS event"); if (ke->initialized) { GST_LOG_OBJECT (ke, "ensuring all headers are in"); if (gst_kate_enc_flush_headers (ke) != GST_FLOW_OK) { GST_WARNING_OBJECT (ke, "Failed to flush headers"); } else { kate_packet kp; int ret; GstClockTime delayed_end = ke->delayed_start + ke->default_spu_duration * GST_SECOND; if (G_UNLIKELY (gst_kate_enc_flush_waiting (ke, delayed_end) != GST_FLOW_OK)) { GST_WARNING_OBJECT (ke, "Failed to encode delayed packet"); /* continue with EOS handling anyway */ } ret = kate_encode_finish (&ke->k, -1, &kp); if (ret < 0) { GST_WARNING_OBJECT (ke, "Failed to encode EOS packet: %d", ret); } else { kate_int64_t granpos = kate_encode_get_granule (&ke->k); GST_LOG_OBJECT (ke, "EOS packet encoded"); if (gst_kate_enc_push_and_free_kate_packet (ke, &kp, granpos, ke->latest_end_time, 0, FALSE)) { GST_WARNING_OBJECT (ke, "Failed to push EOS packet"); } } } } ret = gst_pad_event_default (pad, event); break; default: GST_LOG_OBJECT (ke, "Got unhandled event"); ret = gst_pad_event_default (pad, event); break; } gst_object_unref (ke); return ret; }
static gboolean gst_amc_audio_dec_set_format (GstAudioDecoder * decoder, GstCaps * caps) { GstAmcAudioDec *self; GstStructure *s; GstAmcFormat *format; const gchar *mime; gboolean is_format_change = FALSE; gboolean needs_disable = FALSE; gchar *format_string; gint rate, channels; GError *err = NULL; self = GST_AMC_AUDIO_DEC (decoder); GST_DEBUG_OBJECT (self, "Setting new caps %" GST_PTR_FORMAT, caps); /* Check if the caps change is a real format change or if only irrelevant * parts of the caps have changed or nothing at all. */ is_format_change |= (!self->input_caps || !gst_caps_is_equal (self->input_caps, caps)); needs_disable = self->started; /* If the component is not started and a real format change happens * we have to restart the component. If no real format change * happened we can just exit here. */ if (needs_disable && !is_format_change) { /* Framerate or something minor changed */ self->input_caps_changed = TRUE; GST_DEBUG_OBJECT (self, "Already running and caps did not change the format"); return TRUE; } if (needs_disable && is_format_change) { gst_amc_audio_dec_drain (self); GST_AUDIO_DECODER_STREAM_UNLOCK (self); gst_amc_audio_dec_stop (GST_AUDIO_DECODER (self)); GST_AUDIO_DECODER_STREAM_LOCK (self); gst_amc_audio_dec_close (GST_AUDIO_DECODER (self)); if (!gst_amc_audio_dec_open (GST_AUDIO_DECODER (self))) { GST_ERROR_OBJECT (self, "Failed to open codec again"); return FALSE; } if (!gst_amc_audio_dec_start (GST_AUDIO_DECODER (self))) { GST_ERROR_OBJECT (self, "Failed to start codec again"); } } /* srcpad task is not running at this point */ mime = caps_to_mime (caps); if (!mime) { GST_ERROR_OBJECT (self, "Failed to convert caps to mime"); return FALSE; } s = gst_caps_get_structure (caps, 0); if (!gst_structure_get_int (s, "rate", &rate) || !gst_structure_get_int (s, "channels", &channels)) { GST_ERROR_OBJECT (self, "Failed to get rate/channels"); return FALSE; } format = gst_amc_format_new_audio (mime, rate, channels, &err); if (!format) { GST_ELEMENT_ERROR_FROM_ERROR (self, err); return FALSE; } /* FIXME: These buffers needs to be valid until the codec is stopped again */ g_list_foreach (self->codec_datas, (GFunc) gst_buffer_unref, NULL); g_list_free (self->codec_datas); self->codec_datas = NULL; if (gst_structure_has_field (s, "codec_data")) { const GValue *h = gst_structure_get_value (s, "codec_data"); GstBuffer *codec_data = gst_value_get_buffer (h); GstMapInfo minfo; guint8 *data; gst_buffer_map (codec_data, &minfo, GST_MAP_READ); data = g_memdup (minfo.data, minfo.size); self->codec_datas = g_list_prepend (self->codec_datas, data); gst_amc_format_set_buffer (format, "csd-0", data, minfo.size, &err); if (err) GST_ELEMENT_WARNING_FROM_ERROR (self, err); gst_buffer_unmap (codec_data, &minfo); } else if (gst_structure_has_field (s, "streamheader")) { const GValue *sh = gst_structure_get_value (s, "streamheader"); gint nsheaders = gst_value_array_get_size (sh); GstBuffer *buf; const GValue *h; gint i, j; gchar *fname; GstMapInfo minfo; guint8 *data; for (i = 0, j = 0; i < nsheaders; i++) { h = gst_value_array_get_value (sh, i); buf = gst_value_get_buffer (h); if (strcmp (mime, "audio/vorbis") == 0) { guint8 header_type; gst_buffer_extract (buf, 0, &header_type, 1); /* Only use the identification and setup packets */ if (header_type != 0x01 && header_type != 0x05) continue; } fname = g_strdup_printf ("csd-%d", j); gst_buffer_map (buf, &minfo, GST_MAP_READ); data = g_memdup (minfo.data, minfo.size); self->codec_datas = g_list_prepend (self->codec_datas, data); gst_amc_format_set_buffer (format, fname, data, minfo.size, &err); if (err) GST_ELEMENT_WARNING_FROM_ERROR (self, err); gst_buffer_unmap (buf, &minfo); g_free (fname); j++; } } format_string = gst_amc_format_to_string (format, &err); if (err) GST_ELEMENT_WARNING_FROM_ERROR (self, err); GST_DEBUG_OBJECT (self, "Configuring codec with format: %s", GST_STR_NULL (format_string)); g_free (format_string); if (!gst_amc_codec_configure (self->codec, format, NULL, 0, &err)) { GST_ERROR_OBJECT (self, "Failed to configure codec"); GST_ELEMENT_ERROR_FROM_ERROR (self, err); return FALSE; } gst_amc_format_free (format); if (!gst_amc_codec_start (self->codec, &err)) { GST_ERROR_OBJECT (self, "Failed to start codec"); GST_ELEMENT_ERROR_FROM_ERROR (self, err); return FALSE; } self->spf = -1; /* TODO: Implement for other codecs too */ if (gst_structure_has_name (s, "audio/mpeg")) { gint mpegversion = -1; gst_structure_get_int (s, "mpegversion", &mpegversion); if (mpegversion == 1) { gint layer = -1, mpegaudioversion = -1; gst_structure_get_int (s, "layer", &layer); gst_structure_get_int (s, "mpegaudioversion", &mpegaudioversion); if (layer == 1) self->spf = 384; else if (layer == 2) self->spf = 1152; else if (layer == 3 && mpegaudioversion != -1) self->spf = (mpegaudioversion == 1 ? 1152 : 576); } } self->started = TRUE; self->input_caps_changed = TRUE; /* Start the srcpad loop again */ self->flushing = FALSE; self->downstream_flow_ret = GST_FLOW_OK; gst_pad_start_task (GST_AUDIO_DECODER_SRC_PAD (self), (GstTaskFunction) gst_amc_audio_dec_loop, decoder, NULL); return TRUE; }