* <refsect2>
* <title>Example pipelines</title>
* |[
- * gst-launch v4l2src num-buffers=500 ! video/x-raw-yuv,width=320,height=240 ! ffmpegcolorspace ! qtmux ! filesink location=video.mov
+ * gst-launch v4l2src num-buffers=500 ! video/x-raw,width=320,height=240 ! ffmpegcolorspace ! qtmux ! filesink location=video.mov
* ]|
* Records a video stream captured from a v4l2 device and muxes it into a qt file.
* </refsect2>
#include <glib/gstdio.h>
#include <gst/gst.h>
-#include <gst/base/gstcollectpads.h>
+#include <gst/base/gstcollectpads2.h>
+#include <gst/audio/audio.h>
+#include <gst/video/video.h>
#include <gst/tag/xmpwriter.h>
#include <sys/types.h>
/* pad functions */
static GstPad *gst_qt_mux_request_new_pad (GstElement * element,
- GstPadTemplate * templ, const gchar * name);
+ GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
static void gst_qt_mux_release_pad (GstElement * element, GstPad * pad);
/* event */
srctempl = gst_pad_template_new ("src", GST_PAD_SRC,
GST_PAD_ALWAYS, params->src_caps);
gst_element_class_add_pad_template (element_class, srctempl);
- gst_object_unref (srctempl);
if (params->audio_sink_caps) {
- audiosinktempl = gst_pad_template_new ("audio_%d",
+ audiosinktempl = gst_pad_template_new ("audio_%u",
GST_PAD_SINK, GST_PAD_REQUEST, params->audio_sink_caps);
gst_element_class_add_pad_template (element_class, audiosinktempl);
- gst_object_unref (audiosinktempl);
}
if (params->video_sink_caps) {
- videosinktempl = gst_pad_template_new ("video_%d",
+ videosinktempl = gst_pad_template_new ("video_%u",
GST_PAD_SINK, GST_PAD_REQUEST, params->video_sink_caps);
gst_element_class_add_pad_template (element_class, videosinktempl);
- gst_object_unref (videosinktempl);
}
klass->format = params->prop->format;
GstQTMux * qtmux)
{
GstBuffer *newbuf;
+ GstMapInfo map;
+ gsize size;
GST_LOG_OBJECT (qtmux, "Preparing jpc buffer");
if (buf == NULL)
return NULL;
- newbuf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buf) + 8);
- gst_buffer_copy_metadata (newbuf, buf, GST_BUFFER_COPY_ALL);
+ size = gst_buffer_get_size (buf);
+ newbuf = gst_buffer_new_and_alloc (size + 8);
+ gst_buffer_copy_into (newbuf, buf, GST_BUFFER_COPY_ALL, 8, size);
- GST_WRITE_UINT32_BE (GST_BUFFER_DATA (newbuf), GST_BUFFER_SIZE (newbuf));
- GST_WRITE_UINT32_LE (GST_BUFFER_DATA (newbuf) + 4, FOURCC_jp2c);
+ gst_buffer_map (newbuf, &map, GST_MAP_WRITE);
+ GST_WRITE_UINT32_BE (map.data, map.size);
+ GST_WRITE_UINT32_LE (map.data + 4, FOURCC_jp2c);
- memcpy (GST_BUFFER_DATA (newbuf) + 8, GST_BUFFER_DATA (buf),
- GST_BUFFER_SIZE (buf));
+ gst_buffer_unmap (buf, &map);
gst_buffer_unref (buf);
return newbuf;
GDateDay day;
gchar *str;
- g_return_if_fail (gst_tag_get_type (tag) == GST_TYPE_DATE);
+ g_return_if_fail (gst_tag_get_type (tag) == G_TYPE_DATE);
if (!gst_tag_list_get_date (list, tag, &date) || !date)
return;
{
GValue value = { 0, };
GstBuffer *buf;
+ GstSample *sample;
GstCaps *caps;
GstStructure *structure;
gint flags = 0;
+ GstMapInfo map;
- g_return_if_fail (gst_tag_get_type (tag) == GST_TYPE_BUFFER);
+ g_return_if_fail (gst_tag_get_type (tag) == GST_TYPE_SAMPLE);
if (!gst_tag_list_copy_value (&value, list, tag))
return;
- buf = gst_value_get_buffer (&value);
+ sample = gst_value_get_sample (&value);
+
+ if (!sample)
+ goto done;
+
+ buf = gst_sample_get_buffer (sample);
if (!buf)
goto done;
- caps = gst_buffer_get_caps (buf);
+ caps = gst_sample_get_caps (sample);
if (!caps) {
GST_WARNING_OBJECT (qtmux, "preview image without caps");
goto done;
flags = 13;
else if (gst_structure_has_name (structure, "image/png"))
flags = 14;
- gst_caps_unref (caps);
if (!flags) {
GST_WARNING_OBJECT (qtmux, "preview image format not supported");
goto done;
}
+ gst_buffer_map (buf, &map, GST_MAP_READ);
GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT
- " -> image size %d", GST_FOURCC_ARGS (fourcc), GST_BUFFER_SIZE (buf));
- atom_moov_add_tag (qtmux->moov, fourcc, flags, GST_BUFFER_DATA (buf),
- GST_BUFFER_SIZE (buf));
+ " -> image size %" G_GSIZE_FORMAT "", GST_FOURCC_ARGS (fourcc), map.size);
+ atom_moov_add_tag (qtmux->moov, fourcc, flags, map.data, map.size);
+ gst_buffer_unmap (buf, &map);
done:
g_value_unset (&value);
}
GDate *date = NULL;
GDateYear year;
- g_return_if_fail (gst_tag_get_type (tag) == GST_TYPE_DATE);
+ g_return_if_fail (gst_tag_get_type (tag) == G_TYPE_DATE);
if (!gst_tag_list_get_date (list, tag, &date) || !date)
return;
GstCaps *caps = NULL;
val = gst_tag_list_get_value_index (list, GST_QT_DEMUX_PRIVATE_TAG, i);
- buf = (GstBuffer *) gst_value_get_mini_object (val);
+ buf = (GstBuffer *) gst_value_get_buffer (val);
- if (buf && (caps = gst_buffer_get_caps (buf))) {
+ /* FIXME-0.11 */
+ if (buf && (caps = NULL /*gst_buffer_get_caps (buf) */ )) {
GstStructure *s;
const gchar *style = NULL;
+ GstMapInfo map;
- GST_DEBUG_OBJECT (qtmux, "Found private tag %d/%d; size %d, caps %"
- GST_PTR_FORMAT, i, num_tags, GST_BUFFER_SIZE (buf), caps);
+ gst_buffer_map (buf, &map, GST_MAP_READ);
+ GST_DEBUG_OBJECT (qtmux,
+ "Found private tag %d/%d; size %" G_GSIZE_FORMAT ", caps %"
+ GST_PTR_FORMAT, i, num_tags, map.size, caps);
s = gst_caps_get_structure (caps, 0);
if (s && (style = gst_structure_get_string (s, "style"))) {
/* try to prevent some style tag ending up into another variant
(strcmp (style, "iso") == 0 &&
qtmux_klass->format == GST_QT_MUX_FORMAT_3GP)) {
GST_DEBUG_OBJECT (qtmux, "Adding private tag");
- atom_moov_add_blob_tag (qtmux->moov, GST_BUFFER_DATA (buf),
- GST_BUFFER_SIZE (buf));
+ atom_moov_add_blob_tag (qtmux->moov, map.data, map.size);
}
}
+ gst_buffer_unmap (buf, &map);
gst_caps_unref (caps);
}
}
GstBuffer *buf;
buf = gst_buffer_new ();
- GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data;
- GST_BUFFER_SIZE (buf) = size;
+ gst_buffer_take_memory (buf, -1,
+ gst_memory_new_wrapped (0, data, size, 0, size, data, g_free));
return buf;
}
gboolean mind_fast)
{
GstFlowReturn res;
- guint8 *data;
- guint size;
+ gsize size;
g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
- data = GST_BUFFER_DATA (buf);
- size = GST_BUFFER_SIZE (buf);
-
- GST_LOG_OBJECT (qtmux, "sending buffer size %d", size);
+ size = gst_buffer_get_size (buf);
+ GST_LOG_OBJECT (qtmux, "sending buffer size %" G_GSIZE_FORMAT, size);
if (mind_fast && qtmux->fast_start_file) {
+ GstMapInfo map;
gint ret;
GST_LOG_OBJECT (qtmux, "to temporary file");
- ret = fwrite (data, sizeof (guint8), size, qtmux->fast_start_file);
+ gst_buffer_map (buf, &map, GST_MAP_READ);
+ ret = fwrite (map.data, sizeof (guint8), map.size, qtmux->fast_start_file);
+ gst_buffer_unmap (buf, &map);
gst_buffer_unref (buf);
if (ret != size)
goto write_error;
res = GST_FLOW_OK;
} else {
GST_LOG_OBJECT (qtmux, "downstream");
-
- buf = gst_buffer_make_metadata_writable (buf);
- gst_buffer_set_caps (buf, GST_PAD_CAPS (qtmux->srcpad));
res = gst_pad_push (qtmux->srcpad, buf);
}
* (somehow optimize copy?) */
GST_DEBUG_OBJECT (qtmux, "Sending buffered data");
while (ret == GST_FLOW_OK) {
- gint r;
const int bufsize = 4096;
+ GstMapInfo map;
+ gsize size;
buf = gst_buffer_new_and_alloc (bufsize);
- r = fread (GST_BUFFER_DATA (buf), sizeof (guint8), bufsize,
- qtmux->fast_start_file);
- if (r == 0)
+ gst_buffer_map (buf, &map, GST_MAP_WRITE);
+ size = fread (map.data, sizeof (guint8), bufsize, qtmux->fast_start_file);
+ if (size == 0) {
+ gst_buffer_unmap (buf, &map);
break;
- GST_BUFFER_SIZE (buf) = r;
- GST_LOG_OBJECT (qtmux, "Pushing buffered buffer of size %d", r);
+ }
+ GST_LOG_OBJECT (qtmux, "Pushing buffered buffer of size %d",
+ (gint) map.size);
+ gst_buffer_unmap (buf, &map);
ret = gst_qt_mux_send_buffer (qtmux, buf, offset, FALSE);
buf = NULL;
}
gst_qt_mux_update_mdat_size (GstQTMux * qtmux, guint64 mdat_pos,
guint64 mdat_size, guint64 * offset)
{
- GstEvent *event;
GstBuffer *buf;
gboolean large_file;
+ GstSegment segment;
+ GstMapInfo map;
large_file = (mdat_size > MDAT_LARGE_FILE_LIMIT);
mdat_pos += 8;
/* seek and rewrite the header */
- event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
- mdat_pos, GST_CLOCK_TIME_NONE, 0);
- gst_pad_push_event (qtmux->srcpad, event);
+ gst_segment_init (&segment, GST_FORMAT_BYTES);
+ segment.start = mdat_pos;
+ gst_pad_push_event (qtmux->srcpad, gst_event_new_segment (&segment));
if (large_file) {
buf = gst_buffer_new_and_alloc (sizeof (guint64));
- GST_WRITE_UINT64_BE (GST_BUFFER_DATA (buf), mdat_size + 16);
+ gst_buffer_map (buf, &map, GST_MAP_WRITE);
+ GST_WRITE_UINT64_BE (map.data, mdat_size + 16);
} else {
- guint8 *data;
-
buf = gst_buffer_new_and_alloc (16);
- data = GST_BUFFER_DATA (buf);
- GST_WRITE_UINT32_BE (data, 8);
- GST_WRITE_UINT32_LE (data + 4, FOURCC_free);
- GST_WRITE_UINT32_BE (data + 8, mdat_size + 8);
- GST_WRITE_UINT32_LE (data + 12, FOURCC_mdat);
+ gst_buffer_map (buf, &map, GST_MAP_WRITE);
+ GST_WRITE_UINT32_BE (map.data, 8);
+ GST_WRITE_UINT32_LE (map.data + 4, FOURCC_free);
+ GST_WRITE_UINT32_BE (map.data + 8, mdat_size + 8);
+ GST_WRITE_UINT32_LE (map.data + 12, FOURCC_mdat);
}
+ gst_buffer_unmap (buf, &map);
return gst_qt_mux_send_buffer (qtmux, buf, offset, FALSE);
}
GstStructure *structure;
GValue array = { 0 };
GValue value = { 0 };
- GstCaps *caps;
+ GstCaps *caps, *tcaps;
+
+ tcaps = gst_pad_get_current_caps (mux->srcpad);
+ caps = gst_caps_copy (tcaps);
+ gst_caps_unref (tcaps);
- caps = gst_caps_copy (GST_PAD_CAPS (mux->srcpad));
structure = gst_caps_get_structure (caps, 0);
g_value_init (&array, GST_TYPE_ARRAY);
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
+ GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
g_value_init (&value, GST_TYPE_BUFFER);
gst_value_take_buffer (&value, gst_buffer_ref (buf));
gst_value_array_append_value (&array, &value);
{
GstFlowReturn ret = GST_FLOW_OK;
GstCaps *caps;
+ GstSegment segment;
GST_DEBUG_OBJECT (qtmux, "starting file");
gst_query_parse_seeking (query, NULL, &seekable, NULL, NULL);
GST_INFO_OBJECT (qtmux, "downstream is %sseekable",
seekable ? "" : "not ");
- if (!seekable) {
- qtmux->streamable = TRUE;
- g_object_notify (G_OBJECT (qtmux), "streamable");
- GST_WARNING_OBJECT (qtmux, "downstream is not seekable, but "
- "streamable=false. Will ignore that and create streamable output "
- "instead");
- }
} else {
/* have to assume seeking is supported if query not handled downstream */
- /* FIXME 0.11: change to query not handled => seeking not supported */
GST_WARNING_OBJECT (qtmux, "downstream did not handle seeking query");
+ seekable = FALSE;
+ }
+ if (!seekable) {
+ qtmux->streamable = TRUE;
+ g_object_notify (G_OBJECT (qtmux), "streamable");
+ GST_WARNING_OBJECT (qtmux, "downstream is not seekable, but "
+ "streamable=false. Will ignore that and create streamable output "
+ "instead");
}
gst_query_unref (query);
}
/* let downstream know we think in BYTES and expect to do seeking later on */
- gst_pad_push_event (qtmux->srcpad,
- gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0));
+ gst_segment_init (&segment, GST_FORMAT_BYTES);
+ gst_pad_push_event (qtmux->srcpad, gst_event_new_segment (&segment));
/* initialize our moov recovery file */
GST_OBJECT_LOCK (qtmux);
}
if (qtmux->fragment_sequence) {
- GstEvent *event;
+ GstSegment segment;
if (qtmux->mfra) {
guint8 *data = NULL;
return GST_FLOW_OK;
}
-
timescale = qtmux->timescale;
/* only mvex duration is updated,
* mvhd should be consistent with empty moov
GST_DEBUG_OBJECT (qtmux, "rewriting moov with mvex duration %"
GST_TIME_FORMAT, GST_TIME_ARGS (first_ts));
/* seek and rewrite the header */
- event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
- qtmux->mdat_pos, GST_CLOCK_TIME_NONE, 0);
- gst_pad_push_event (qtmux->srcpad, event);
+ gst_segment_init (&segment, GST_FORMAT_BYTES);
+ segment.start = qtmux->mdat_pos;
+ gst_pad_push_event (qtmux->srcpad, gst_event_new_segment (&segment));
/* no need to seek back */
return gst_qt_mux_send_moov (qtmux, NULL, FALSE);
}
pad->traf = NULL;
atom_moof_copy_data (moof, &data, &size, &offset);
buffer = _gst_buffer_new_take_data (data, offset);
- GST_LOG_OBJECT (qtmux, "writing moof size %d", GST_BUFFER_SIZE (buffer));
+ GST_LOG_OBJECT (qtmux, "writing moof size %" G_GSIZE_FORMAT,
+ gst_buffer_get_size (buffer));
ret = gst_qt_mux_send_buffer (qtmux, buffer, &qtmux->header_size, FALSE);
/* and actual data */
total_size = 0;
for (i = 0; i < atom_array_get_len (&pad->fragment_buffers); i++) {
total_size +=
- GST_BUFFER_SIZE (atom_array_index (&pad->fragment_buffers, i));
+ gst_buffer_get_size (atom_array_index (&pad->fragment_buffers, i));
}
GST_LOG_OBJECT (qtmux, "writing %d buffers, total_size %d",
buf = pad->buf_entries[pad->buf_head];
pad->buf_entries[pad->buf_head++] = NULL;
pad->buf_head %= wrap;
- buf = gst_buffer_make_metadata_writable (buf);
+ buf = gst_buffer_make_writable (buf);
/* track original ts (= pts ?) for later */
GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_TIMESTAMP (buf);
GST_BUFFER_TIMESTAMP (buf) = ts;
if (G_LIKELY (buf != NULL && GST_CLOCK_TIME_IS_VALID (pad->first_ts) &&
pad->first_ts != 0)) {
- buf = gst_buffer_make_metadata_writable (buf);
+ buf = gst_buffer_make_writable (buf);
check_and_subtract_ts (qtmux, &GST_BUFFER_TIMESTAMP (buf), pad->first_ts);
}
/* when we obtain the first_ts we subtract from all stored buffers we have,
/* for computing the avg bitrate */
if (G_LIKELY (last_buf)) {
- pad->total_bytes += GST_BUFFER_SIZE (last_buf);
+ pad->total_bytes += gst_buffer_get_size (last_buf);
pad->total_duration += duration;
}
buffer (= chunk)), but can also be fixed-packet-size codecs like ADPCM
*/
sample_size = pad->sample_size;
- if (GST_BUFFER_SIZE (last_buf) % sample_size != 0)
+ if (gst_buffer_get_size (last_buf) % sample_size != 0)
goto fragmented_sample;
/* note: qt raw audio storage warps it implicitly into a timewise
* perfect stream, discarding buffer times */
nsamples = gst_util_uint64_scale_round (GST_BUFFER_DURATION (last_buf),
atom_trak_get_timescale (pad->trak), GST_SECOND);
} else {
- nsamples = GST_BUFFER_SIZE (last_buf) / sample_size;
+ nsamples = gst_buffer_get_size (last_buf) / sample_size;
}
duration = GST_BUFFER_DURATION (last_buf) / nsamples;
pad->last_dts += duration * nsamples;
} else {
nsamples = 1;
- sample_size = GST_BUFFER_SIZE (last_buf);
+ sample_size = gst_buffer_get_size (last_buf);
if (pad->have_dts) {
gint64 scaled_dts;
pad->last_dts = GST_BUFFER_OFFSET_END (last_buf);
}
if (G_UNLIKELY (qtmux->state == GST_QT_MUX_STATE_EOS))
- return GST_FLOW_UNEXPECTED;
+ return GST_FLOW_EOS;
best_pad = (GstQTPad *) cdata;
if (ret == GST_FLOW_OK) {
GST_DEBUG_OBJECT (qtmux, "Pushing eos");
gst_pad_push_event (qtmux->srcpad, gst_event_new_eos ());
- ret = GST_FLOW_UNEXPECTED;
+ ret = GST_FLOW_EOS;
} else {
GST_WARNING_OBJECT (qtmux, "Failed to stop file: %s",
gst_flow_get_name (ret));
* the old caps are a subset of the new one (this means upstream
* added more info to the caps, as both should be 'fixed' caps) */
if (qtpad->fourcc) {
- GstCaps *current_caps = NULL;
- gboolean is_subset;
- g_object_get (pad, "caps", ¤t_caps, NULL);
+ GstCaps *current_caps;
+
+ current_caps = gst_pad_get_current_caps (pad);
g_assert (caps != NULL);
- is_subset = gst_qtmux_caps_is_subset_full (qtmux, current_caps, caps);
- gst_caps_unref (current_caps);
- if (!is_subset) {
+ if (!gst_qtmux_caps_is_subset_full (qtmux, current_caps, caps)) {
+ gst_caps_unref (current_caps);
goto refuse_renegotiation;
}
GST_DEBUG_OBJECT (qtmux,
"pad %s accepted renegotiation to %" GST_PTR_FORMAT " from %"
- GST_PTR_FORMAT, GST_PAD_NAME (pad), caps, GST_PAD_CAPS (pad));
+ GST_PTR_FORMAT, GST_PAD_NAME (pad), caps, current_caps);
+ gst_caps_unref (current_caps);
}
GST_DEBUG_OBJECT (qtmux, "%s:%s, caps=%" GST_PTR_FORMAT,
"assuming 'raw'");
}
- if (!codec_data || GST_BUFFER_SIZE (codec_data) < 2)
+ if (!codec_data || gst_buffer_get_size ((GstBuffer *) codec_data) < 2)
GST_WARNING_OBJECT (qtmux, "no (valid) codec_data for AAC audio");
else {
- guint8 profile = GST_READ_UINT8 (GST_BUFFER_DATA (codec_data));
+ guint8 profile;
+ gst_buffer_extract ((GstBuffer *) codec_data, 0, &profile, 1);
/* warn if not Low Complexity profile */
profile >>= 3;
if (profile != 2)
entry.samples_per_packet = 320;
entry.bytes_per_sample = 2;
ext_atom = build_amr_extension ();
- } else if (strcmp (mimetype, "audio/x-raw-int") == 0) {
- gint width;
- gint depth;
- gint endianness;
- gboolean sign;
-
- if (!gst_structure_get_int (structure, "width", &width) ||
- !gst_structure_get_int (structure, "depth", &depth) ||
- !gst_structure_get_boolean (structure, "signed", &sign)) {
- GST_DEBUG_OBJECT (qtmux, "broken caps, width/depth/signed field missing");
- goto refuse_caps;
- }
+ } else if (strcmp (mimetype, "audio/x-raw") == 0) {
+ GstAudioInfo info;
- if (depth <= 8) {
- endianness = G_BYTE_ORDER;
- } else if (!gst_structure_get_int (structure, "endianness", &endianness)) {
- GST_DEBUG_OBJECT (qtmux, "broken caps, endianness field missing");
+ gst_audio_info_init (&info);
+ if (!gst_audio_info_from_caps (&info, caps))
goto refuse_caps;
- }
/* spec has no place for a distinction in these */
- if (width != depth) {
+ if (info.finfo->width != info.finfo->depth) {
GST_DEBUG_OBJECT (qtmux, "width must be same as depth!");
goto refuse_caps;
}
- if (sign) {
- if (endianness == G_LITTLE_ENDIAN)
+ if ((info.finfo->flags & GST_AUDIO_FORMAT_FLAG_SIGNED)) {
+ if (info.finfo->endianness == G_LITTLE_ENDIAN)
entry.fourcc = FOURCC_sowt;
- else if (endianness == G_BIG_ENDIAN)
+ else if (info.finfo->endianness == G_BIG_ENDIAN)
entry.fourcc = FOURCC_twos;
/* maximum backward compatibility; only new version for > 16 bit */
- if (depth <= 16)
+ if (info.finfo->depth <= 16)
entry.version = 0;
/* not compressed in any case */
entry.compression_id = 0;
/* QT spec says: max at 16 bit even if sample size were actually larger,
* however, most players (e.g. QuickTime!) seem to disagree, so ... */
- entry.sample_size = depth;
- entry.bytes_per_sample = depth / 8;
+ entry.sample_size = info.finfo->depth;
+ entry.bytes_per_sample = info.finfo->depth / 8;
entry.samples_per_packet = 1;
- entry.bytes_per_packet = depth / 8;
- entry.bytes_per_frame = entry.bytes_per_packet * channels;
+ entry.bytes_per_packet = info.finfo->depth / 8;
+ entry.bytes_per_frame = entry.bytes_per_packet * info.channels;
} else {
- if (width == 8 && depth == 8) {
+ if (info.finfo->width == 8 && info.finfo->depth == 8) {
/* fall back to old 8-bit version */
entry.fourcc = FOURCC_raw_;
entry.version = 0;
goto refuse_caps;
}
}
- constant_size = (depth / 8) * channels;
+ constant_size = (info.finfo->depth / 8) * info.channels;
} else if (strcmp (mimetype, "audio/x-alaw") == 0) {
entry.fourcc = FOURCC_alaw;
entry.samples_per_packet = 1023;
} else if (strcmp (mimetype, "audio/x-alac") == 0) {
GstBuffer *codec_config;
gint len;
+ GstMapInfo map;
entry.fourcc = FOURCC_alac;
+ gst_buffer_map ((GstBuffer *) codec_data, &map, GST_MAP_READ);
/* let's check if codec data already comes with 'alac' atom prefix */
- if (!codec_data || (len = GST_BUFFER_SIZE (codec_data)) < 28) {
+ if (!codec_data || (len = map.size) < 28) {
GST_DEBUG_OBJECT (qtmux, "broken caps, codec data missing");
+ gst_buffer_unmap ((GstBuffer *) codec_data, &map);
goto refuse_caps;
}
- if (GST_READ_UINT32_LE (GST_BUFFER_DATA (codec_data) + 4) == FOURCC_alac) {
+ if (GST_READ_UINT32_LE (map.data + 4) == FOURCC_alac) {
len -= 8;
- codec_config = gst_buffer_create_sub ((GstBuffer *) codec_data, 8, len);
+ codec_config =
+ gst_buffer_copy_region ((GstBuffer *) codec_data, 0, 8, len);
} else {
codec_config = gst_buffer_ref ((GstBuffer *) codec_data);
}
+ gst_buffer_unmap ((GstBuffer *) codec_data, &map);
if (len != 28) {
/* does not look good, but perhaps some trailing unneeded stuff */
GST_WARNING_OBJECT (qtmux, "unexpected codec-data size, possibly broken");
else
ext_atom = build_codec_data_extension (FOURCC_alac, codec_config);
/* set some more info */
+ gst_buffer_map (codec_config, &map, GST_MAP_READ);
entry.bytes_per_sample = 2;
- entry.samples_per_packet =
- GST_READ_UINT32_BE (GST_BUFFER_DATA (codec_config) + 4);
+ entry.samples_per_packet = GST_READ_UINT32_BE (map.data + 4);
+ gst_buffer_unmap (codec_config, &map);
gst_buffer_unref (codec_config);
}
* the old caps are a subset of the new one (this means upstream
* added more info to the caps, as both should be 'fixed' caps) */
if (qtpad->fourcc) {
- GstCaps *current_caps = NULL;
- gboolean is_subset;
- g_object_get (pad, "caps", ¤t_caps, NULL);
+ GstCaps *current_caps;
+
+ current_caps = gst_pad_get_current_caps (pad);
g_assert (caps != NULL);
- is_subset = gst_qtmux_caps_is_subset_full (qtmux, current_caps, caps);
- gst_caps_unref (current_caps);
- if (!is_subset) {
+ if (!gst_qtmux_caps_is_subset_full (qtmux, current_caps, caps)) {
+ gst_caps_unref (current_caps);
goto refuse_renegotiation;
}
GST_DEBUG_OBJECT (qtmux,
"pad %s accepted renegotiation to %" GST_PTR_FORMAT " from %"
- GST_PTR_FORMAT, GST_PAD_NAME (pad), caps, GST_PAD_CAPS (pad));
+ GST_PTR_FORMAT, GST_PAD_NAME (pad), caps, current_caps);
+ gst_caps_unref (current_caps);
}
GST_DEBUG_OBJECT (qtmux, "%s:%s, caps=%" GST_PTR_FORMAT,
sync = TRUE;
/* now map onto a fourcc, and some extra properties */
- if (strcmp (mimetype, "video/x-raw-rgb") == 0) {
- gint bpp;
+ if (strcmp (mimetype, "video/x-raw") == 0) {
+ const gchar *format;
+ GstVideoFormat fmt;
+ const GstVideoFormatInfo *vinfo;
- entry.fourcc = FOURCC_raw_;
- gst_structure_get_int (structure, "bpp", &bpp);
- entry.depth = bpp;
- sync = FALSE;
- } else if (strcmp (mimetype, "video/x-raw-yuv") == 0) {
- guint32 format = 0;
+ format = gst_structure_get_string (structure, "format");
+ fmt = gst_video_format_from_string (format);
+ vinfo = gst_video_format_get_info (fmt);
- sync = FALSE;
- gst_structure_get_fourcc (structure, "format", &format);
- switch (format) {
- case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
+ switch (fmt) {
+ case GST_VIDEO_FORMAT_UYVY:
if (depth == -1)
depth = 24;
entry.fourcc = FOURCC_2vuy;
entry.depth = depth;
+ sync = FALSE;
+ break;
+ default:
+ if (GST_VIDEO_FORMAT_INFO_FLAGS (vinfo) & GST_VIDEO_FORMAT_FLAG_RGB) {
+ entry.fourcc = FOURCC_raw_;
+ entry.depth = GST_VIDEO_FORMAT_INFO_PSTRIDE (vinfo, 0) * 8;
+ sync = FALSE;
+ }
break;
}
} else if (strcmp (mimetype, "video/x-h263") == 0) {
sync = FALSE;
} else if (strcmp (mimetype, "image/x-j2c") == 0 ||
strcmp (mimetype, "image/x-jpc") == 0) {
- guint32 fourcc;
+ const gchar *colorspace;
const GValue *cmap_array;
const GValue *cdef_array;
gint ncomp = 0;
ext_atom = NULL;
entry.fourcc = FOURCC_mjp2;
sync = FALSE;
- if (gst_structure_get_fourcc (structure, "fourcc", &fourcc) &&
+
+ colorspace = gst_structure_get_string (structure, "colorspace");
+ if (colorspace &&
(ext_atom =
- build_jp2h_extension (qtpad->trak, width, height, fourcc, ncomp,
+ build_jp2h_extension (qtpad->trak, width, height, colorspace, ncomp,
cmap_array, cdef_array)) != NULL) {
ext_atom_list = g_list_append (ext_atom_list, ext_atom);
} else if (strcmp (mimetype, "video/x-qt-part") == 0) {
guint32 fourcc;
- gst_structure_get_fourcc (structure, "format", &fourcc);
+ gst_structure_get_uint (structure, "format", &fourcc);
entry.fourcc = fourcc;
qtpad->have_dts = TRUE;
} else if (strcmp (mimetype, "video/x-mp4-part") == 0) {
guint32 fourcc;
- gst_structure_get_fourcc (structure, "format", &fourcc);
+ gst_structure_get_uint (structure, "format", &fourcc);
entry.fourcc = fourcc;
qtpad->have_dts = TRUE;
}
refuse_renegotiation:
{
GST_WARNING_OBJECT (qtmux,
- "pad %s refused renegotiation to %" GST_PTR_FORMAT " from %"
- GST_PTR_FORMAT, GST_PAD_NAME (pad), caps, GST_PAD_CAPS (pad));
+ "pad %s refused renegotiation to %" GST_PTR_FORMAT, GST_PAD_NAME (pad),
+ caps);
gst_object_unref (qtmux);
return FALSE;
}
GstQTMux *qtmux;
guint32 avg_bitrate = 0, max_bitrate = 0;
GstPad *pad = data->pad;
+ gboolean ret = FALSE;
qtmux = GST_QT_MUX_CAST (user_data);
switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_CAPS:
+ {
+ GstCaps *caps;
+ GstQTPad *collect_pad;
+
+ gst_event_parse_caps (event, &caps);
+
+ /* find stream data */
+ collect_pad = (GstQTPad *) gst_pad_get_element_private (pad);
+ g_assert (collect_pad);
+ g_assert (collect_pad->set_caps);
+
+ ret = collect_pad->set_caps (pad, caps);
+ gst_event_unref (event);
+ break;
+ }
case GST_EVENT_TAG:{
GstTagList *list;
GstTagSetter *setter = GST_TAG_SETTER (qtmux);
qtpad->max_bitrate = max_bitrate;
}
+ gst_event_unref (event);
+ ret = TRUE;
break;
}
default:
+ ret = gst_pad_event_default (data->pad, GST_OBJECT (qtmux), event);
+ break;
+ case GST_EVENT_EOS:
+ case GST_EVENT_SEGMENT:
+ gst_event_unref (event);
+ ret = TRUE;
break;
}
- /* now GstCollectPads2 can take care of the rest, e.g. EOS */
- return FALSE;
+ return ret;
}
static void
static GstPad *
gst_qt_mux_request_new_pad (GstElement * element,
- GstPadTemplate * templ, const gchar * req_name)
+ GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps)
{
GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
GstQTMux *qtmux = GST_QT_MUX_CAST (element);
GstPad *newpad;
gboolean audio;
gchar *name;
+ gint pad_id;
if (templ->direction != GST_PAD_SINK)
goto wrong_direction;
if (qtmux->state > GST_QT_MUX_STATE_STARTED)
goto too_late;
- if (templ == gst_element_class_get_pad_template (klass, "audio_%d")) {
+ if (templ == gst_element_class_get_pad_template (klass, "audio_%u")) {
audio = TRUE;
- name = g_strdup_printf ("audio_%02d", qtmux->audio_pads++);
- } else if (templ == gst_element_class_get_pad_template (klass, "video_%d")) {
+ if (req_name != NULL && sscanf (req_name, "audio_%u", &pad_id) == 1) {
+ name = g_strdup (req_name);
+ } else {
+ name = g_strdup_printf ("audio_%u", qtmux->audio_pads++);
+ }
+ } else if (templ == gst_element_class_get_pad_template (klass, "video_%u")) {
audio = FALSE;
- name = g_strdup_printf ("video_%02d", qtmux->video_pads++);
+ if (req_name != NULL && sscanf (req_name, "video_%u", &pad_id) == 1) {
+ name = g_strdup (req_name);
+ } else {
+ name = g_strdup_printf ("video_%u", qtmux->video_pads++);
+ }
} else
goto wrong_template;
/* set up pad functions */
if (audio)
- gst_pad_set_setcaps_function (newpad,
- GST_DEBUG_FUNCPTR (gst_qt_mux_audio_sink_set_caps));
+ collect_pad->set_caps = GST_DEBUG_FUNCPTR (gst_qt_mux_audio_sink_set_caps);
else
- gst_pad_set_setcaps_function (newpad,
- GST_DEBUG_FUNCPTR (gst_qt_mux_video_sink_set_caps));
+ collect_pad->set_caps = GST_DEBUG_FUNCPTR (gst_qt_mux_video_sink_set_caps);
gst_pad_set_active (newpad, TRUE);
gst_element_add_pad (element, newpad);