static void put_packet (GstPluginLoader * l, guint type, guint32 tag, const guint8 * payload, guint32 payload_len) { guint8 *out; guint len = payload_len + HEADER_SIZE; if (l->tx_buf_write + len >= l->tx_buf_size) { GST_LOG ("Expanding tx buf from %d to %d for packet of size %d", l->tx_buf_size, l->tx_buf_write + len + BUF_GROW_EXTRA, len); l->tx_buf_size = l->tx_buf_write + len + BUF_GROW_EXTRA; l->tx_buf = g_realloc (l->tx_buf, l->tx_buf_size); } out = l->tx_buf + l->tx_buf_write; /* one byte packet type */ out[0] = type; /* 3 byte packet tag number */ GST_WRITE_UINT24_BE (out + 1, tag); /* 4 bytes packet length */ GST_WRITE_UINT32_BE (out + 4, payload_len); /* payload */ memcpy (out + HEADER_SIZE, payload, payload_len); /* Write magic into the header */ GST_WRITE_UINT32_BE (out + 8, HEADER_MAGIC); l->tx_buf_write += len; gst_poll_fd_ctl_write (l->fdset, &l->fd_w, TRUE); }
static gpointer make_samr_magic_cookie (GstBuffer * codec_data, gsize * len) { guint8 *res; *len = 48; res = g_malloc0 (0x30); /* 12 first bytes are 'frma' (format) atom with 'samr' value */ GST_WRITE_UINT32_BE (res, 0xc); GST_WRITE_UINT32_LE (res + 4, QT_MAKE_FOURCC_BE ('f', 'r', 'm', 'a')); GST_WRITE_UINT32_LE (res + 8, QT_MAKE_FOURCC_BE ('s', 'a', 'm', 'r')); /* 10 bytes for 'enda' atom with 0 */ GST_WRITE_UINT32_BE (res + 12, 10); GST_WRITE_UINT32_LE (res + 16, QT_MAKE_FOURCC_BE ('e', 'n', 'd', 'a')); /* 17(+1) bytes for the codec_data contents */ GST_WRITE_UINT32_BE (res + 22, 18); memcpy (res + 26, GST_BUFFER_DATA (codec_data) + 4, 17); /* yes... we need to replace 'damr' by 'samr'. Blame Apple ! */ GST_WRITE_UINT8 (res + 26, 's'); /* Terminator atom */ GST_WRITE_UINT32_BE (res + 40, 8); #if DEBUG_DUMP gst_util_dump_mem (res, 48); #endif return res; }
gboolean atoms_recov_write_trak_samples (FILE * f, AtomTRAK * trak, guint32 nsamples, guint32 delta, guint32 size, guint64 chunk_offset, gboolean sync, gboolean do_pts, gint64 pts_offset) { guint8 data[TRAK_BUFFER_ENTRY_INFO_SIZE]; /* * We have to write a TrakBufferEntryInfo */ GST_WRITE_UINT32_BE (data + 0, trak->tkhd.track_ID); GST_WRITE_UINT32_BE (data + 4, nsamples); GST_WRITE_UINT32_BE (data + 8, delta); GST_WRITE_UINT32_BE (data + 12, size); GST_WRITE_UINT64_BE (data + 16, chunk_offset); if (sync) GST_WRITE_UINT8 (data + 24, 1); else GST_WRITE_UINT8 (data + 24, 0); if (do_pts) { GST_WRITE_UINT8 (data + 25, 1); GST_WRITE_UINT64_BE (data + 26, pts_offset); } else { GST_WRITE_UINT8 (data + 25, 0); GST_WRITE_UINT64_BE (data + 26, 0); } return fwrite (data, 1, TRAK_BUFFER_ENTRY_INFO_SIZE, f) == TRAK_BUFFER_ENTRY_INFO_SIZE; }
static gpointer make_alac_magic_cookie (GstBuffer * codec_data, gsize * len) { guint8 *res; if (GST_BUFFER_SIZE (codec_data) < 4) return NULL; *len = 20 + GST_BUFFER_SIZE (codec_data); res = g_malloc0 (*len); /* 12 first bytes are 'frma' (format) atom with 'alac' value */ GST_WRITE_UINT32_BE (res, 0xc); /* Atom length: 12 bytes */ GST_WRITE_UINT32_LE (res + 4, QT_MAKE_FOURCC_BE ('f', 'r', 'm', 'a')); GST_WRITE_UINT32_LE (res + 8, QT_MAKE_FOURCC_BE ('a', 'l', 'a', 'c')); /* Write the codec_data, but with the first four bytes reversed (different endianness). This is the 'alac' atom. */ GST_WRITE_UINT32_BE (res + 12, GST_READ_UINT32_LE (GST_BUFFER_DATA (codec_data))); memcpy (res + 16, GST_BUFFER_DATA (codec_data) + 4, GST_BUFFER_SIZE (codec_data) - 4); /* Terminator atom */ GST_WRITE_UINT32_BE (res + 12 + GST_BUFFER_SIZE (codec_data), 8); GST_WRITE_UINT32_BE (res + 12 + GST_BUFFER_SIZE (codec_data) + 4, 0); return res; }
/** * Writes the moov's timescale to the file * This simply writes a guint32 in BE. */ static gboolean atoms_recov_write_moov_timescale (FILE * f, guint32 timescale) { guint8 data[4]; GST_WRITE_UINT32_BE (data, timescale); return fwrite (data, 4, 1, f) == 1; }
/** * Writes the number of traks to the file. * This simply writes a guint32 in BE. */ static gboolean atoms_recov_write_traks_number (FILE * f, guint32 traks) { guint8 data[4]; GST_WRITE_UINT32_BE (data, traks); return fwrite (data, 4, 1, f) == 1; }
static void _serialize_u32 (AmfSerializer * serializer, int value) { if (_serialize_check (serializer, 4)) { GST_WRITE_UINT32_BE (serializer->data + serializer->offset, value); serializer->offset += 4; } }
/** * gst_rtp_buffer_set_csrc: * @buffer: the buffer * @idx: the CSRC index to set * @csrc: the CSRC in host order to set at @idx * * Modify the CSRC at index @idx in @buffer to @csrc. */ void gst_rtp_buffer_set_csrc (GstBuffer * buffer, guint8 idx, guint32 csrc) { guint8 *data; data = GST_BUFFER_DATA (buffer); g_return_if_fail (idx < GST_RTP_HEADER_CSRC_COUNT (data)); GST_WRITE_UINT32_BE (GST_RTP_HEADER_CSRC_LIST_OFFSET (data, idx), csrc); }
static GstBuffer * gst_h264_parse_wrap_nal (GstH264Parse * h264parse, guint format, guint8 * data, guint size) { GstBuffer *buf; const guint nl = h264parse->nal_length_size; buf = gst_buffer_new_and_alloc (size + nl + 4); if (format == GST_H264_PARSE_FORMAT_AVC) { GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), size << (32 - 8 * nl)); } else { g_assert (nl == 4); GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), 1); } GST_BUFFER_SIZE (buf) = size + nl; memcpy (GST_BUFFER_DATA (buf) + nl, data, size); return buf; }
EXPORT_C #endif void gst_rtp_buffer_set_csrc (GstBuffer * buffer, guint8 idx, guint32 csrc) { g_return_if_fail (GST_IS_BUFFER (buffer)); g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL); g_return_if_fail (idx < GST_RTP_HEADER_CSRC_COUNT (buffer)); GST_WRITE_UINT32_BE (GST_RTP_HEADER_CSRC_LIST_OFFSET (buffer, idx), csrc); }
static void flv_write_tag (guint8 * data, guint8 packet_type, guint payload_size, guint32 timestamp) { data[0] = packet_type; GST_WRITE_UINT24_BE (&data[1], payload_size); if (timestamp > EXT_TIMESTAMP_LIMIT) { GST_WRITE_UINT32_BE (&data[4], timestamp); } else { GST_WRITE_UINT24_BE (&data[4], timestamp); data[7] = 0; } GST_WRITE_UINT24_BE (&data[8], 0); }
GstBuffer * flv_generate_tag (const guint8 * data, gsize size, guint8 id, guint32 timestamp) { guint size_with_header = size + flv_tag_header_size; guint tag_size = size_with_header + 4; guint8 *tag = g_malloc (tag_size); flv_write_tag (tag, id, size, timestamp); memcpy (&tag[flv_tag_header_size], data, size); /* write the total length (size_with_header) in the last 4 bytes */ GST_WRITE_UINT32_BE (&tag[size_with_header], size_with_header); return gst_buffer_new_wrapped (tag, tag_size); }
static ImageDescription * image_description_for_avc1 (GstBuffer * buf) { ImageDescription *desc = NULL; guint8 *pos; desc = g_malloc0 (sizeof (ImageDescription) + GST_BUFFER_SIZE (buf) + 8); pos = (guint8 *) desc + sizeof (ImageDescription); desc->idSize = sizeof (ImageDescription) + GST_BUFFER_SIZE (buf) + 8; /* write size in Big-Endian */ GST_WRITE_UINT32_BE (pos, GST_BUFFER_SIZE (buf) + 8); GST_WRITE_UINT32_LE (pos + 4, QT_MAKE_FOURCC_BE ('a', 'v', 'c', 'C')); g_memmove (pos + 8, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); return desc; }
static guint8 * gss_adaptive_assemble_chunk (GssTransaction * t, GssAdaptive * adaptive, GssAdaptiveLevel * level, GssIsomFragment * fragment) { GError *error = NULL; guint8 *mdat_data; int fd; gboolean ret; g_return_val_if_fail (t != NULL, NULL); g_return_val_if_fail (adaptive != NULL, NULL); g_return_val_if_fail (level != NULL, NULL); g_return_val_if_fail (fragment != NULL, NULL); fd = open (level->filename, O_RDONLY); if (fd < 0) { GST_WARNING ("failed to open \"%s\", error=\"%s\", broken manifest?", level->filename, g_strerror (errno)); gss_transaction_error_not_found (t, "failed to open file (broken manifest?)"); return NULL; } mdat_data = g_malloc (fragment->mdat_size); GST_WRITE_UINT32_BE (mdat_data, fragment->mdat_size); GST_WRITE_UINT32_LE (mdat_data + 4, GST_MAKE_FOURCC ('m', 'd', 'a', 't')); ret = gss_sglist_load (fragment->sglist, fd, mdat_data + 8, &error); if (!ret) { gss_transaction_error_not_found (t, error->message); g_error_free (error); g_free (mdat_data); close (fd); return NULL; } close (fd); return mdat_data; }
static CamReturn send_profile_reply (CamResourceManager * mgr, CamSLSession * session) { CamReturn ret; guint8 *buffer; guint8 *apdu_body; guint buffer_size; guint offset; GList *resource_ids; guint resource_ids_size; GList *walk; resource_ids = cam_al_get_resource_ids (CAM_AL_APPLICATION (mgr)->al); resource_ids_size = g_list_length (resource_ids) * 4; cam_al_calc_buffer_size (CAM_AL_APPLICATION (mgr)->al, resource_ids_size, &buffer_size, &offset); buffer = g_malloc (buffer_size); apdu_body = buffer + offset; for (walk = resource_ids; walk != NULL; walk = walk->next) { GST_WRITE_UINT32_BE (apdu_body, GPOINTER_TO_UINT (walk->data)); apdu_body += 4; } g_list_free (resource_ids); GST_DEBUG ("sending profile reply"); ret = cam_al_application_write (CAM_AL_APPLICATION (mgr), session, TAG_PROFILE_REPLY, buffer, buffer_size, resource_ids_size); g_free (buffer); return ret; }
static void run_output_order_test (gint n_linked) { /* This test creates a multiqueue with 2 linked output, and 3 outputs that * return 'not-linked' when data is pushed, then verifies that all buffers * are received on not-linked pads only after earlier buffers on the * 'linked' pads are made */ GstElement *pipe; GstElement *mq; GstPad *inputpads[5]; GstPad *sinkpads[5]; struct PadData pad_data[5]; guint32 max_linked_id; guint32 eos_seen; GMutex *mutex; GCond *cond; gint i; const gint NPADS = 5; const gint NBUFFERS = 1000; mutex = g_mutex_new (); cond = g_cond_new (); pipe = gst_bin_new ("testbin"); mq = gst_element_factory_make ("multiqueue", NULL); fail_unless (mq != NULL); gst_bin_add (GST_BIN (pipe), mq); /* No limits */ g_object_set (mq, "max-size-bytes", (guint) 0, "max-size-buffers", (guint) 0, "max-size-time", (guint64) 0, "extra-size-bytes", (guint) 0, "extra-size-buffers", (guint) 0, "extra-size-time", (guint64) 0, NULL); /* Construct NPADS dummy output pads. The first 'n_linked' return FLOW_OK, the rest * return NOT_LINKED. The not-linked ones check the expected ordering of * output buffers */ for (i = 0; i < NPADS; i++) { GstPad *mq_srcpad, *mq_sinkpad; gchar *name; name = g_strdup_printf ("dummysrc%d", i); inputpads[i] = gst_pad_new (name, GST_PAD_SRC); g_free (name); gst_pad_set_getcaps_function (inputpads[i], mq_dummypad_getcaps); mq_sinkpad = gst_element_get_request_pad (mq, "sink%d"); fail_unless (mq_sinkpad != NULL); gst_pad_link (inputpads[i], mq_sinkpad); gst_pad_set_active (inputpads[i], TRUE); mq_srcpad = mq_sinkpad_to_srcpad (mq, mq_sinkpad); name = g_strdup_printf ("dummysink%d", i); sinkpads[i] = gst_pad_new (name, GST_PAD_SINK); g_free (name); gst_pad_set_chain_function (sinkpads[i], mq_dummypad_chain); gst_pad_set_event_function (sinkpads[i], mq_dummypad_event); gst_pad_set_getcaps_function (sinkpads[i], mq_dummypad_getcaps); pad_data[i].pad_num = i; pad_data[i].max_linked_id_ptr = &max_linked_id; pad_data[i].eos_count_ptr = &eos_seen; pad_data[i].is_linked = (i < n_linked ? TRUE : FALSE); pad_data[i].n_linked = n_linked; pad_data[i].cond = cond; pad_data[i].mutex = mutex; pad_data[i].first_buf = TRUE; gst_pad_set_element_private (sinkpads[i], pad_data + i); gst_pad_link (mq_srcpad, sinkpads[i]); gst_pad_set_active (sinkpads[i], TRUE); gst_object_unref (mq_sinkpad); gst_object_unref (mq_srcpad); } /* Run the test. Push 1000 buffers through the multiqueue in a pattern */ max_linked_id = 0; eos_seen = 0; gst_element_set_state (pipe, GST_STATE_PLAYING); for (i = 0; i < NBUFFERS; i++) { const guint8 pad_pattern[] = { 0, 0, 0, 0, 1, 1, 2, 1, 0, 2, 3, 2, 3, 1, 4 }; const guint n = sizeof (pad_pattern) / sizeof (guint8); guint8 cur_pad; GstBuffer *buf; GstFlowReturn ret; cur_pad = pad_pattern[i % n]; buf = gst_buffer_new_and_alloc (4); g_static_mutex_lock (&_check_lock); fail_if (buf == NULL); g_static_mutex_unlock (&_check_lock); GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), i + 1); GST_BUFFER_TIMESTAMP (buf) = (i + 1) * GST_SECOND; ret = gst_pad_push (inputpads[cur_pad], buf); g_static_mutex_lock (&_check_lock); if (pad_data[cur_pad].is_linked) { fail_unless (ret == GST_FLOW_OK, "Push on pad %d returned %d when FLOW_OK was expected", cur_pad, ret); } else { /* Expect OK initially, then NOT_LINKED when the srcpad starts pushing */ fail_unless (ret == GST_FLOW_OK || ret == GST_FLOW_NOT_LINKED, "Push on pad %d returned %d when FLOW_OK or NOT_LINKED was expected", cur_pad, ret); } g_static_mutex_unlock (&_check_lock); } for (i = 0; i < NPADS; i++) { gst_pad_push_event (inputpads[i], gst_event_new_eos ()); } /* Wait while the buffers are processed */ g_mutex_lock (mutex); while (eos_seen < 5) { g_cond_wait (cond, mutex); } g_mutex_unlock (mutex); /* Clean up */ for (i = 0; i < 5; i++) { GstPad *mq_input = gst_pad_get_peer (inputpads[i]); gst_pad_unlink (inputpads[i], mq_input); gst_element_release_request_pad (mq, mq_input); gst_object_unref (mq_input); gst_object_unref (inputpads[i]); gst_object_unref (sinkpads[i]); } gst_element_set_state (pipe, GST_STATE_NULL); gst_object_unref (pipe); g_cond_free (cond); g_mutex_free (mutex); }
static GstFlowReturn gst_jasper_enc_get_data (GstJasperEnc * enc, guint8 * data, GstBuffer ** outbuf) { GstFlowReturn ret = GST_FLOW_OK; jas_stream_t *stream = NULL; gint i; guint size, boxsize; g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR); *outbuf = NULL; boxsize = (enc->mode == GST_JP2ENC_MODE_J2C) ? 8 : 0; if (!(stream = jas_stream_memopen (NULL, 0))) goto fail_stream; for (i = 0; i < enc->channels; ++i) { gint x, y, cwidth, cheight, inc, stride, cmpt; guint8 *row_pix, *in_pix; glong *tb; cmpt = i; inc = enc->inc[i]; stride = enc->stride[i]; cheight = enc->cheight[cmpt]; cwidth = enc->cwidth[cmpt]; GST_LOG_OBJECT (enc, "write component %d<=%d, size %dx%d, offset %d, inc %d, stride %d", i, cmpt, cwidth, cheight, enc->offset[i], inc, stride); row_pix = data + enc->offset[i]; for (y = 0; y < cheight; y++) { in_pix = row_pix; tb = enc->buf; for (x = 0; x < cwidth; x++) { *tb = *in_pix; in_pix += inc; tb++; } if (jas_image_writecmpt2 (enc->image, cmpt, 0, y, cwidth, 1, enc->buf)) goto fail_image; row_pix += stride; } } GST_LOG_OBJECT (enc, "all components written"); if (jas_image_encode (enc->image, stream, enc->fmt, (char *) "sop")) goto fail_encode; GST_LOG_OBJECT (enc, "image encoded"); size = jas_stream_length (stream); ret = gst_pad_alloc_buffer_and_set_caps (enc->srcpad, GST_BUFFER_OFFSET_NONE, size + boxsize, GST_PAD_CAPS (enc->srcpad), outbuf); if (ret != GST_FLOW_OK) goto no_buffer; data = GST_BUFFER_DATA (*outbuf); if (jas_stream_flush (stream) || jas_stream_rewind (stream) < 0 || jas_stream_read (stream, data + boxsize, size) < size) goto fail_image_out; if (boxsize) { /* write atom prefix */ GST_WRITE_UINT32_BE (data, size + 8); GST_WRITE_UINT32_LE (data + 4, GST_MAKE_FOURCC ('j', 'p', '2', 'c')); } done: if (stream) jas_stream_close (stream); return ret; /* ERRORS */ fail_stream: { GST_DEBUG_OBJECT (enc, "Failed to create inputstream."); goto fail; } fail_encode: { GST_DEBUG_OBJECT (enc, "Failed to encode image."); goto fail; } fail_image: { GST_DEBUG_OBJECT (enc, "Failed to process input image."); goto fail; } fail_image_out: { GST_DEBUG_OBJECT (enc, "Failed to process encoded image."); goto fail; } fail: { if (*outbuf) gst_buffer_unref (*outbuf); *outbuf = NULL; GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL), (NULL)); ret = GST_FLOW_ERROR; goto done; } no_buffer: { GST_DEBUG_OBJECT (enc, "Failed to create outbuffer - %s", gst_flow_get_name (ret)); goto done; } }
static GstFlowReturn gst_openjpeg_enc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame) { GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (encoder); GstFlowReturn ret = GST_FLOW_OK; #ifdef HAVE_OPENJPEG_1 opj_cinfo_t *enc; GstMapInfo map; guint length; opj_cio_t *io; #else opj_codec_t *enc; opj_stream_t *stream; MemStream mstream; #endif opj_image_t *image; GstVideoFrame vframe; GST_DEBUG_OBJECT (self, "Handling frame"); enc = opj_create_compress (self->codec_format); if (!enc) goto initialization_error; #ifdef HAVE_OPENJPEG_1 if (G_UNLIKELY (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >= GST_LEVEL_TRACE)) { opj_event_mgr_t callbacks; callbacks.error_handler = gst_openjpeg_enc_opj_error; callbacks.warning_handler = gst_openjpeg_enc_opj_warning; callbacks.info_handler = gst_openjpeg_enc_opj_info; opj_set_event_mgr ((opj_common_ptr) enc, &callbacks, self); } else { opj_set_event_mgr ((opj_common_ptr) enc, NULL, NULL); } #else if (G_UNLIKELY (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >= GST_LEVEL_TRACE)) { opj_set_info_handler (enc, gst_openjpeg_enc_opj_info, self); opj_set_warning_handler (enc, gst_openjpeg_enc_opj_warning, self); opj_set_error_handler (enc, gst_openjpeg_enc_opj_error, self); } else { opj_set_info_handler (enc, NULL, NULL); opj_set_warning_handler (enc, NULL, NULL); opj_set_error_handler (enc, NULL, NULL); } #endif if (!gst_video_frame_map (&vframe, &self->input_state->info, frame->input_buffer, GST_MAP_READ)) goto map_read_error; image = gst_openjpeg_enc_fill_image (self, &vframe); if (!image) goto fill_image_error; gst_video_frame_unmap (&vframe); opj_setup_encoder (enc, &self->params, image); #ifdef HAVE_OPENJPEG_1 io = opj_cio_open ((opj_common_ptr) enc, NULL, 0); if (!io) goto open_error; if (!opj_encode (enc, io, image, NULL)) goto encode_error; opj_image_destroy (image); length = cio_tell (io); ret = gst_video_encoder_allocate_output_frame (encoder, frame, length + (self->is_jp2c ? 8 : 0)); if (ret != GST_FLOW_OK) goto allocate_error; gst_buffer_fill (frame->output_buffer, self->is_jp2c ? 8 : 0, io->buffer, length); if (self->is_jp2c) { gst_buffer_map (frame->output_buffer, &map, GST_MAP_WRITE); GST_WRITE_UINT32_BE (map.data, length + 8); GST_WRITE_UINT32_BE (map.data + 4, GST_MAKE_FOURCC ('j', 'p', '2', 'c')); gst_buffer_unmap (frame->output_buffer, &map); } opj_cio_close (io); opj_destroy_compress (enc); #else stream = opj_stream_create (4096, OPJ_FALSE); if (!stream) goto open_error; mstream.allocsize = 4096; mstream.data = g_malloc (mstream.allocsize); mstream.offset = 0; mstream.size = 0; opj_stream_set_read_function (stream, read_fn); opj_stream_set_write_function (stream, write_fn); opj_stream_set_skip_function (stream, skip_fn); opj_stream_set_seek_function (stream, seek_fn); opj_stream_set_user_data (stream, &mstream); opj_stream_set_user_data_length (stream, mstream.size); if (!opj_start_compress (enc, image, stream)) goto encode_error; if (!opj_encode (enc, stream)) goto encode_error; if (!opj_end_compress (enc, stream)) goto encode_error; opj_image_destroy (image); opj_stream_destroy (stream); opj_destroy_codec (enc); frame->output_buffer = gst_buffer_new (); if (self->is_jp2c) { GstMapInfo map; GstMemory *mem; mem = gst_allocator_alloc (NULL, 8, NULL); gst_memory_map (mem, &map, GST_MAP_WRITE); GST_WRITE_UINT32_BE (map.data, mstream.size + 8); GST_WRITE_UINT32_BE (map.data + 4, GST_MAKE_FOURCC ('j', 'p', '2', 'c')); gst_memory_unmap (mem, &map); gst_buffer_append_memory (frame->output_buffer, mem); } gst_buffer_append_memory (frame->output_buffer, gst_memory_new_wrapped (0, mstream.data, mstream.allocsize, 0, mstream.size, NULL, (GDestroyNotify) g_free)); #endif ret = gst_video_encoder_finish_frame (encoder, frame); return ret; initialization_error: { gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, LIBRARY, INIT, ("Failed to initialize OpenJPEG encoder"), (NULL)); return GST_FLOW_ERROR; } map_read_error: { #ifdef HAVE_OPENJPEG_1 opj_destroy_compress (enc); #else opj_destroy_codec (enc); #endif gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, CORE, FAILED, ("Failed to map input buffer"), (NULL)); return GST_FLOW_ERROR; } fill_image_error: { #ifdef HAVE_OPENJPEG_1 opj_destroy_compress (enc); #else opj_destroy_codec (enc); #endif gst_video_frame_unmap (&vframe); gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, LIBRARY, INIT, ("Failed to fill OpenJPEG image"), (NULL)); return GST_FLOW_ERROR; } open_error: { opj_image_destroy (image); #ifdef HAVE_OPENJPEG_1 opj_destroy_compress (enc); #else opj_destroy_codec (enc); #endif gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, LIBRARY, INIT, ("Failed to open OpenJPEG data"), (NULL)); return GST_FLOW_ERROR; } encode_error: { #ifdef HAVE_OPENJPEG_1 opj_cio_close (io); opj_image_destroy (image); opj_destroy_compress (enc); #else opj_stream_destroy (stream); g_free (mstream.data); opj_image_destroy (image); opj_destroy_codec (enc); #endif gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, STREAM, ENCODE, ("Failed to encode OpenJPEG stream"), (NULL)); return GST_FLOW_ERROR; } #ifdef HAVE_OPENJPEG_1 allocate_error: { opj_cio_close (io); opj_destroy_compress (enc); gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, CORE, FAILED, ("Failed to allocate output buffer"), (NULL)); return ret; } #endif }
static gboolean new_packet_cb (guint8 * data, guint len, void *user_data, gint64 new_pcr) { /* Called when the TsMux has prepared a packet for output. Return FALSE * on error */ MpegTsMux *mux = (MpegTsMux *) user_data; GstBuffer *buf, *out_buf; GstFlowReturn ret; gfloat current_ts; gint64 m2ts_pcr, pcr_bytes, chunk_bytes; gint8 *temp_ptr; gint64 ts_rate; if (mux->m2ts_mode == TRUE) { /* Enters when the m2ts-mode is set true */ buf = gst_buffer_new_and_alloc (M2TS_PACKET_LENGTH); if (mux->is_delta) { GST_LOG_OBJECT (mux, "marking as delta unit"); GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); } else { GST_DEBUG_OBJECT (mux, "marking as non-delta unit"); mux->is_delta = TRUE; } if (G_UNLIKELY (buf == NULL)) { mux->last_flow_ret = GST_FLOW_ERROR; return FALSE; } gst_buffer_set_caps (buf, GST_PAD_CAPS (mux->srcpad)); /* copies the ts data of 188 bytes to the m2ts buffer at an offset of 4 bytes of timestamp */ memcpy (GST_BUFFER_DATA (buf) + 4, data, len); if (new_pcr >= 0) { /*when there is a pcr value in ts data */ pcr_bytes = 0; if (mux->first_pcr) { /*Incase of first pcr */ /*writing the 4 byte timestamp value */ GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), new_pcr); GST_LOG_OBJECT (mux, "Outputting a packet of length %d", M2TS_PACKET_LENGTH); ret = gst_pad_push (mux->srcpad, buf); if (G_UNLIKELY (ret != GST_FLOW_OK)) { mux->last_flow_ret = ret; return FALSE; } mux->first_pcr = FALSE; mux->previous_pcr = new_pcr; pcr_bytes = M2TS_PACKET_LENGTH; } chunk_bytes = gst_adapter_available (mux->adapter); if (G_UNLIKELY (chunk_bytes)) { /* calculate rate based on latest and previous pcr values */ ts_rate = ((chunk_bytes * STANDARD_TIME_CLOCK) / (new_pcr - mux->previous_pcr)); while (1) { /*loop till all the accumulated ts packets are transformed to m2ts packets and pushed */ current_ts = ((gfloat) mux->previous_pcr / STANDARD_TIME_CLOCK) + ((gfloat) pcr_bytes / ts_rate); m2ts_pcr = (((gint64) (STANDARD_TIME_CLOCK * current_ts / 300) & TWO_POW_33_MINUS1) * 300) + ((gint64) (STANDARD_TIME_CLOCK * current_ts) % 300); temp_ptr = (gint8 *) & m2ts_pcr; out_buf = gst_adapter_take_buffer (mux->adapter, M2TS_PACKET_LENGTH); if (G_UNLIKELY (!out_buf)) break; gst_buffer_set_caps (out_buf, GST_PAD_CAPS (mux->srcpad)); /*writing the 4 byte timestamp value */ GST_WRITE_UINT32_BE (GST_BUFFER_DATA (out_buf), m2ts_pcr); GST_LOG_OBJECT (mux, "Outputting a packet of length %d", M2TS_PACKET_LENGTH); ret = gst_pad_push (mux->srcpad, out_buf); if (G_UNLIKELY (ret != GST_FLOW_OK)) { mux->last_flow_ret = ret; return FALSE; } pcr_bytes += M2TS_PACKET_LENGTH; } mux->previous_pcr = m2ts_pcr; } } else /* If theres no pcr in current ts packet then push the packet to an adapter, which is used to create m2ts packets */ gst_adapter_push (mux->adapter, buf); } else { /* In case of Normal Ts packets */ GST_LOG_OBJECT (mux, "Outputting a packet of length %d", len); buf = gst_buffer_new_and_alloc (len); if (G_UNLIKELY (buf == NULL)) { mux->last_flow_ret = GST_FLOW_ERROR; return FALSE; } gst_buffer_set_caps (buf, GST_PAD_CAPS (mux->srcpad)); memcpy (GST_BUFFER_DATA (buf), data, len); GST_BUFFER_TIMESTAMP (buf) = mux->last_ts; if (!mux->streamheader_sent) { guint pid = ((data[1] & 0x1f) << 8) | data[2]; /* if it's a PAT or a PMT */ if (pid == 0x00 || (pid >= TSMUX_START_PMT_PID && pid < TSMUX_START_ES_PID)) { mux->streamheader = g_list_append (mux->streamheader, gst_buffer_copy (buf)); } else if (mux->streamheader) { mpegtsdemux_set_header_on_caps (mux); mux->streamheader_sent = TRUE; /* don't unset the streamheaders by pushing old caps */ gst_buffer_set_caps (buf, GST_PAD_CAPS (mux->srcpad)); } } if (mux->is_delta) { GST_LOG_OBJECT (mux, "marking as delta unit"); GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); } else { GST_DEBUG_OBJECT (mux, "marking as non-delta unit"); mux->is_delta = TRUE; } ret = gst_pad_push (mux->srcpad, buf); if (G_UNLIKELY (ret != GST_FLOW_OK)) { mux->last_flow_ret = ret; return FALSE; } } return TRUE; }
static gboolean do_plugin_load (GstPluginLoader * l, const gchar * filename, guint tag) { GstPlugin *newplugin; GList *chunks = NULL; GST_DEBUG ("Plugin scanner loading file %s. tag %u", filename, tag); #if 0 /* Test code - crash based on filename */ if (strstr (filename, "coreelements") == NULL) { g_printerr ("Crashing on file %s\n", filename); g_printerr ("%d", *(gint *) (NULL)); } #endif newplugin = gst_plugin_load_file ((gchar *) filename, NULL); if (newplugin) { guint hdr_pos; guint offset; /* Now serialise the plugin details and send */ if (!_priv_gst_registry_chunks_save_plugin (&chunks, gst_registry_get_default (), newplugin)) goto fail; /* Store where the header is, write an empty one, then write * all the payload chunks, then fix up the header size */ hdr_pos = l->tx_buf_write; offset = HEADER_SIZE; put_packet (l, PACKET_PLUGIN_DETAILS, tag, NULL, 0); if (chunks) { GList *walk; for (walk = chunks; walk; walk = g_list_next (walk)) { GstRegistryChunk *cur = walk->data; put_chunk (l, cur, &offset); _priv_gst_registry_chunk_free (cur); } g_list_free (chunks); /* Store the size of the written payload */ GST_WRITE_UINT32_BE (l->tx_buf + hdr_pos + 4, offset - HEADER_SIZE); } #if 0 /* Test code - corrupt the tx buffer based on filename */ if (strstr (filename, "sink") != NULL) { int fd, res; g_printerr ("Corrupting tx buf on file %s\n", filename); fd = open ("/dev/urandom", O_RDONLY); res = read (fd, l->tx_buf, l->tx_buf_size); close (fd); } #endif gst_object_unref (newplugin); } else { put_packet (l, PACKET_PLUGIN_DETAILS, tag, NULL, 0); } return TRUE; fail: put_packet (l, PACKET_PLUGIN_DETAILS, tag, NULL, 0); if (chunks) { GList *walk; for (walk = chunks; walk; walk = g_list_next (walk)) { GstRegistryChunk *cur = walk->data; _priv_gst_registry_chunk_free (cur); } g_list_free (chunks); } return FALSE; }
static ImageDescription * image_description_for_mp4v (GstBuffer * buf) { ImageDescription *desc = NULL; guint32 offset = sizeof (ImageDescription); guint8 *location; GST_LOG ("buf %p , size:%d", buf, GST_BUFFER_SIZE (buf)); /* this image description contains: * ImageDescription sizeof(ImageDescription) * esds atom 34 bytes * buffer GST_BUFFER_SIZE (buf) * ending 3 bytes */ desc = g_malloc0 (offset + 37 + GST_BUFFER_SIZE (buf)); desc->idSize = offset + 37 + GST_BUFFER_SIZE (buf); location = (guint8 *) desc + offset; /* Fill in ESDS */ /* size */ GST_WRITE_UINT32_BE (location, 37 + GST_BUFFER_SIZE (buf)); /* atom */ GST_WRITE_UINT32_LE (location + 4, GST_MAKE_FOURCC ('e', 's', 'd', 's')); /* version + flags */ QT_WRITE_UINT32 (location + 8, 0); /* tag */ QT_WRITE_UINT8 (location + 12, 0x3); /* size (buffsize + 23) */ QT_WRITE_UINT8 (location + 13, GST_BUFFER_SIZE (buf) + 23); /* ESID */ QT_WRITE_UINT16 (location + 14, 0); /* priority */ QT_WRITE_UINT8 (location + 16, 0); /* tag */ QT_WRITE_UINT8 (location + 17, 0x4); /* size (buffsize + 8) */ QT_WRITE_UINT8 (location + 18, GST_BUFFER_SIZE (buf) + 15); /* object type */ QT_WRITE_UINT8 (location + 19, 0x20); /* stream type */ QT_WRITE_UINT8 (location + 20, 0x11); /* buffersize db */ QT_WRITE_UINT24 (location + 21, 13640); /* max bitrate */ QT_WRITE_UINT32 (location + 24, 1849648); /* avg bitrate */ QT_WRITE_UINT32 (location + 28, 918191); /* tag */ QT_WRITE_UINT8 (location + 32, 0x05); /* size */ QT_WRITE_UINT8 (location + 33, GST_BUFFER_SIZE (buf)); /* codec data */ g_memmove (location + 34, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); /* end */ QT_WRITE_UINT8 (location + 34 + GST_BUFFER_SIZE (buf), 0x06); QT_WRITE_UINT8 (location + 34 + GST_BUFFER_SIZE (buf) + 1, 0x01); QT_WRITE_UINT8 (location + 34 + GST_BUFFER_SIZE (buf) + 2, 0x02); return desc; }
static void gst_vp8_enc_set_stream_info (GstVPXEnc * enc, GstCaps * caps, GstVideoInfo * info) { GstStructure *s; GstVideoEncoder *video_encoder; GstBuffer *stream_hdr, *vorbiscomment; const GstTagList *iface_tags; GValue array = { 0, }; GValue value = { 0, }; guint8 *data = NULL; GstMapInfo map; video_encoder = GST_VIDEO_ENCODER (enc); s = gst_caps_get_structure (caps, 0); /* put buffers in a fixed list */ g_value_init (&array, GST_TYPE_ARRAY); g_value_init (&value, GST_TYPE_BUFFER); /* Create Ogg stream-info */ stream_hdr = gst_buffer_new_and_alloc (26); gst_buffer_map (stream_hdr, &map, GST_MAP_WRITE); data = map.data; GST_WRITE_UINT8 (data, 0x4F); GST_WRITE_UINT32_BE (data + 1, 0x56503830); /* "VP80" */ GST_WRITE_UINT8 (data + 5, 0x01); /* stream info header */ GST_WRITE_UINT8 (data + 6, 1); /* Major version 1 */ GST_WRITE_UINT8 (data + 7, 0); /* Minor version 0 */ GST_WRITE_UINT16_BE (data + 8, GST_VIDEO_INFO_WIDTH (info)); GST_WRITE_UINT16_BE (data + 10, GST_VIDEO_INFO_HEIGHT (info)); GST_WRITE_UINT24_BE (data + 12, GST_VIDEO_INFO_PAR_N (info)); GST_WRITE_UINT24_BE (data + 15, GST_VIDEO_INFO_PAR_D (info)); GST_WRITE_UINT32_BE (data + 18, GST_VIDEO_INFO_FPS_N (info)); GST_WRITE_UINT32_BE (data + 22, GST_VIDEO_INFO_FPS_D (info)); gst_buffer_unmap (stream_hdr, &map); GST_BUFFER_FLAG_SET (stream_hdr, GST_BUFFER_FLAG_HEADER); gst_value_set_buffer (&value, stream_hdr); gst_value_array_append_value (&array, &value); g_value_unset (&value); gst_buffer_unref (stream_hdr); iface_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (video_encoder)); if (iface_tags) { vorbiscomment = gst_tag_list_to_vorbiscomment_buffer (iface_tags, (const guint8 *) "OVP80\2 ", 7, "Encoded with GStreamer vp8enc " PACKAGE_VERSION); GST_BUFFER_FLAG_SET (vorbiscomment, GST_BUFFER_FLAG_HEADER); g_value_init (&value, GST_TYPE_BUFFER); gst_value_set_buffer (&value, vorbiscomment); gst_value_array_append_value (&array, &value); g_value_unset (&value); gst_buffer_unref (vorbiscomment); } gst_structure_set_value (s, "streamheader", &array); g_value_unset (&array); }
static GstVideoOverlayComposition * gst_dvbsub_overlay_subs_to_comp (GstDVBSubOverlay * overlay, DVBSubtitles * subs) { GstVideoOverlayComposition *comp = NULL; GstVideoOverlayRectangle *rect; gint width, height, dw, dh, wx, wy; gint i; g_return_val_if_fail (subs != NULL && subs->num_rects > 0, NULL); width = GST_VIDEO_INFO_WIDTH (&overlay->info); height = GST_VIDEO_INFO_HEIGHT (&overlay->info); dw = subs->display_def.display_width; dh = subs->display_def.display_height; GST_LOG_OBJECT (overlay, "converting %d rectangles for display %dx%d -> video %dx%d", subs->num_rects, dw, dh, width, height); if (subs->display_def.window_flag) { wx = subs->display_def.window_x; wy = subs->display_def.window_y; GST_LOG_OBJECT (overlay, "display window %dx%d @ (%d, %d)", subs->display_def.window_width, subs->display_def.window_height, wx, wy); } else { wx = 0; wy = 0; } for (i = 0; i < subs->num_rects; i++) { DVBSubtitleRect *srect = &subs->rects[i]; GstBuffer *buf; gint w, h; guint8 *in_data; guint32 *palette, *data; gint rx, ry, rw, rh, stride; gint k, l; GstMapInfo map; GST_LOG_OBJECT (overlay, "rectangle %d: %dx%d @ (%d, %d)", i, srect->w, srect->h, srect->x, srect->y); w = srect->w; h = srect->h; buf = gst_buffer_new_and_alloc (w * h * 4); gst_buffer_map (buf, &map, GST_MAP_WRITE); data = (guint32 *) map.data; in_data = srect->pict.data; palette = srect->pict.palette; stride = srect->pict.rowstride; for (k = 0; k < h; k++) { for (l = 0; l < w; l++) { guint32 ayuv; ayuv = palette[*in_data]; GST_WRITE_UINT32_BE (data, ayuv); in_data++; data++; } in_data += stride - w; } gst_buffer_unmap (buf, &map); /* this is assuming the subtitle rectangle coordinates are relative * to the window (if there is one) within a display of specified dimension. * Coordinate wrt the latter is then scaled to the actual dimension of * the video we are dealing with here. */ rx = gst_util_uint64_scale (wx + srect->x, width, dw); ry = gst_util_uint64_scale (wy + srect->y, height, dh); rw = gst_util_uint64_scale (srect->w, width, dw); rh = gst_util_uint64_scale (srect->h, height, dh); GST_LOG_OBJECT (overlay, "rectangle %d rendered: %dx%d @ (%d, %d)", i, rw, rh, rx, ry); gst_buffer_add_video_meta (buf, GST_VIDEO_FRAME_FLAG_NONE, GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_YUV, w, h); rect = gst_video_overlay_rectangle_new_raw (buf, rx, ry, rw, rh, 0); g_assert (rect); if (comp) { gst_video_overlay_composition_add_rectangle (comp, rect); } else { comp = gst_video_overlay_composition_new (rect); } gst_video_overlay_rectangle_unref (rect); gst_buffer_unref (buf); } return comp; }
static GstCaps * gst_vp8_enc_get_caps (GstBaseVideoEncoder * base_video_encoder) { GstCaps *caps; const GstVideoState *state; GstTagList *tags = NULL; const GstTagList *iface_tags; GstBuffer *stream_hdr, *vorbiscomment; guint8 *data; GstStructure *s; GValue array = { 0 }; GValue value = { 0 }; state = gst_base_video_encoder_get_state (base_video_encoder); caps = gst_caps_new_simple ("video/x-vp8", "width", G_TYPE_INT, state->width, "height", G_TYPE_INT, state->height, "framerate", GST_TYPE_FRACTION, state->fps_n, state->fps_d, "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n, state->par_d, NULL); s = gst_caps_get_structure (caps, 0); /* put buffers in a fixed list */ g_value_init (&array, GST_TYPE_ARRAY); g_value_init (&value, GST_TYPE_BUFFER); /* Create Ogg stream-info */ stream_hdr = gst_buffer_new_and_alloc (26); data = GST_BUFFER_DATA (stream_hdr); GST_WRITE_UINT8 (data, 0x4F); GST_WRITE_UINT32_BE (data + 1, 0x56503830); /* "VP80" */ GST_WRITE_UINT8 (data + 5, 0x01); /* stream info header */ GST_WRITE_UINT8 (data + 6, 1); /* Major version 1 */ GST_WRITE_UINT8 (data + 7, 0); /* Minor version 0 */ GST_WRITE_UINT16_BE (data + 8, state->width); GST_WRITE_UINT16_BE (data + 10, state->height); GST_WRITE_UINT24_BE (data + 12, state->par_n); GST_WRITE_UINT24_BE (data + 15, state->par_d); GST_WRITE_UINT32_BE (data + 18, state->fps_n); GST_WRITE_UINT32_BE (data + 22, state->fps_d); GST_BUFFER_FLAG_SET (stream_hdr, GST_BUFFER_FLAG_IN_CAPS); gst_value_set_buffer (&value, stream_hdr); gst_value_array_append_value (&array, &value); g_value_unset (&value); gst_buffer_unref (stream_hdr); iface_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (base_video_encoder)); if (iface_tags) { vorbiscomment = gst_tag_list_to_vorbiscomment_buffer ((iface_tags) ? iface_tags : tags, (const guint8 *) "OVP80\2 ", 7, "Encoded with GStreamer vp8enc " PACKAGE_VERSION); GST_BUFFER_FLAG_SET (vorbiscomment, GST_BUFFER_FLAG_IN_CAPS); g_value_init (&value, GST_TYPE_BUFFER); gst_value_set_buffer (&value, vorbiscomment); gst_value_array_append_value (&array, &value); g_value_unset (&value); gst_buffer_unref (vorbiscomment); } gst_structure_set_value (s, "streamheader", &array); g_value_unset (&array); return caps; }
gboolean moov_recov_write_file (MoovRecovFile * moovrf, MdatRecovFile * mdatrf, FILE * outf, GError ** err) { guint8 auxdata[16]; guint8 *data = NULL; guint8 *prefix_data = NULL; guint8 *mvhd_data = NULL; guint8 *trak_data = NULL; guint32 moov_size = 0; gint i; guint64 stbl_children_size = 0; guint8 *stbl_children = NULL; guint32 longest_duration = 0; guint16 version; /* check the version */ if (fseek (moovrf->file, 0, SEEK_SET) != 0) { g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE, "Failed to seek to the start of the moov recovery file"); goto fail; } if (fread (auxdata, 1, 2, moovrf->file) != 2) { g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE, "Failed to read version from file"); } version = GST_READ_UINT16_BE (auxdata); if (version != ATOMS_RECOV_FILE_VERSION) { g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_VERSION, "Input file version (%u) is not supported in this version (%u)", version, ATOMS_RECOV_FILE_VERSION); return FALSE; } /* write the ftyp */ prefix_data = g_malloc (moovrf->prefix_size); if (fread (prefix_data, 1, moovrf->prefix_size, moovrf->file) != moovrf->prefix_size) { g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE, "Failed to read the ftyp atom from file"); goto fail; } if (fwrite (prefix_data, 1, moovrf->prefix_size, outf) != moovrf->prefix_size) { ATOMS_RECOV_OUTPUT_WRITE_ERROR (err); goto fail; } g_free (prefix_data); prefix_data = NULL; /* need to calculate the moov size beforehand to add the offset to * chunk offset entries */ moov_size += moovrf->mvhd_size + 8; /* mvhd + moov size + fourcc */ for (i = 0; i < moovrf->num_traks; i++) { TrakRecovData *trak = &(moovrf->traks_rd[i]); guint32 duration; /* in moov's timescale */ guint32 trak_size; /* convert trak duration to moov's duration */ duration = gst_util_uint64_scale_round (trak->duration, moovrf->timescale, trak->timescale); if (duration > longest_duration) longest_duration = duration; trak_size = trak_recov_data_get_trak_atom_size (trak); if (trak_size == 0) { g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_GENERIC, "Failed to estimate trak atom size"); goto fail; } moov_size += trak_size; } /* add chunks offsets */ for (i = 0; i < moovrf->num_traks; i++) { TrakRecovData *trak = &(moovrf->traks_rd[i]); /* 16 for the mdat header */ gint64 offset = moov_size + ftell (outf) + 16; atom_stco64_chunks_add_offset (&trak->stbl.stco64, offset); } /* write the moov */ GST_WRITE_UINT32_BE (auxdata, moov_size); GST_WRITE_UINT32_LE (auxdata + 4, FOURCC_moov); if (fwrite (auxdata, 1, 8, outf) != 8) { ATOMS_RECOV_OUTPUT_WRITE_ERROR (err); goto fail; } /* write the mvhd */ mvhd_data = g_malloc (moovrf->mvhd_size); if (fseek (moovrf->file, moovrf->mvhd_pos, SEEK_SET) != 0) goto fail; if (fread (mvhd_data, 1, moovrf->mvhd_size, moovrf->file) != moovrf->mvhd_size) goto fail; GST_WRITE_UINT32_BE (mvhd_data + 20, moovrf->timescale); GST_WRITE_UINT32_BE (mvhd_data + 24, longest_duration); if (fwrite (mvhd_data, 1, moovrf->mvhd_size, outf) != moovrf->mvhd_size) { ATOMS_RECOV_OUTPUT_WRITE_ERROR (err); goto fail; } g_free (mvhd_data); mvhd_data = NULL; /* write the traks, this is the tough part because we need to update: * - stbl atom * - sizes of atoms from stbl to trak * - trak duration */ for (i = 0; i < moovrf->num_traks; i++) { TrakRecovData *trak = &(moovrf->traks_rd[i]); guint trak_data_size; guint32 stbl_new_size; guint32 minf_new_size; guint32 mdia_new_size; guint32 trak_new_size; guint32 size_diff; guint32 duration; /* in moov's timescale */ /* convert trak duration to moov's duration */ duration = gst_util_uint64_scale_round (trak->duration, moovrf->timescale, trak->timescale); stbl_children = moov_recov_get_stbl_children_data (moovrf, trak, &stbl_children_size); if (stbl_children == NULL) goto fail; /* calc the new size of the atoms from stbl to trak in the atoms tree */ stbl_new_size = trak->stsd_size + stbl_children_size + 8; size_diff = stbl_new_size - trak->stbl_size; minf_new_size = trak->minf_size + size_diff; mdia_new_size = trak->mdia_size + size_diff; trak_new_size = trak->trak_size + size_diff; if (fseek (moovrf->file, trak->file_offset, SEEK_SET) != 0) goto fail; trak_data_size = trak->post_stsd_offset - trak->file_offset; trak_data = g_malloc (trak_data_size); if (fread (trak_data, 1, trak_data_size, moovrf->file) != trak_data_size) { goto fail; } /* update the size values in those read atoms before writing */ GST_WRITE_UINT32_BE (trak_data, trak_new_size); GST_WRITE_UINT32_BE (trak_data + (trak->mdia_file_offset - trak->file_offset), mdia_new_size); GST_WRITE_UINT32_BE (trak_data + (trak->minf_file_offset - trak->file_offset), minf_new_size); GST_WRITE_UINT32_BE (trak_data + (trak->stbl_file_offset - trak->file_offset), stbl_new_size); /* update duration values in tkhd and mdhd */ GST_WRITE_UINT32_BE (trak_data + (trak->tkhd_file_offset - trak->file_offset) + 28, duration); GST_WRITE_UINT32_BE (trak_data + (trak->mdhd_file_offset - trak->file_offset) + 24, trak->duration); if (fwrite (trak_data, 1, trak_data_size, outf) != trak_data_size) { ATOMS_RECOV_OUTPUT_WRITE_ERROR (err); goto fail; } if (fwrite (stbl_children, 1, stbl_children_size, outf) != stbl_children_size) { ATOMS_RECOV_OUTPUT_WRITE_ERROR (err); goto fail; } g_free (trak_data); trak_data = NULL; g_free (stbl_children); stbl_children = NULL; } /* write the mdat */ /* write the header first */ GST_WRITE_UINT32_BE (auxdata, 1); GST_WRITE_UINT32_LE (auxdata + 4, FOURCC_mdat); GST_WRITE_UINT64_BE (auxdata + 8, mdatrf->mdat_size); if (fwrite (auxdata, 1, 16, outf) != 16) { ATOMS_RECOV_OUTPUT_WRITE_ERROR (err); goto fail; } /* now read the mdat data and output to the file */ if (fseek (mdatrf->file, mdatrf->mdat_start + (mdatrf->rawfile ? 0 : mdatrf->mdat_header_size), SEEK_SET) != 0) goto fail; data = g_malloc (4096); while (!feof (mdatrf->file)) { gint read, write; read = fread (data, 1, 4096, mdatrf->file); write = fwrite (data, 1, read, outf); if (write != read) { g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE, "Failed to copy data to output file: %s", g_strerror (errno)); goto fail; } } g_free (data); return TRUE; fail: g_free (stbl_children); g_free (mvhd_data); g_free (prefix_data); g_free (trak_data); g_free (data); return FALSE; }
static gboolean handle_rx_packet (GstPluginLoader * l, guint pack_type, guint32 tag, guint8 * payload, guint payload_len) { gboolean res = TRUE; switch (pack_type) { case PACKET_EXIT: gst_poll_fd_ctl_read (l->fdset, &l->fd_r, FALSE); if (l->is_child) { /* Respond */ put_packet (l, PACKET_EXIT, 0, NULL, 0); } l->rx_done = TRUE; return TRUE; case PACKET_LOAD_PLUGIN:{ if (!l->is_child) return TRUE; /* Payload is the filename to load */ res = do_plugin_load (l, (gchar *) payload, tag); break; } case PACKET_PLUGIN_DETAILS:{ gchar *tmp = (gchar *) payload; PendingPluginEntry *entry = NULL; GList *cur; GST_DEBUG_OBJECT (l->registry, "Received plugin details from child w/ tag %u. %d bytes info", tag, payload_len); /* Assume that tagged details come back in the order * we requested, and delete anything before (but not * including) this one */ cur = l->pending_plugins; while (cur) { PendingPluginEntry *e = (PendingPluginEntry *) (cur->data); if (e->tag > tag) break; if (e->tag == tag) { entry = e; break; } else { cur = g_list_delete_link (cur, cur); g_free (e->filename); g_slice_free (PendingPluginEntry, e); } } l->pending_plugins = cur; if (cur == NULL) l->pending_plugins_tail = NULL; if (payload_len > 0) { GstPlugin *newplugin = NULL; if (!_priv_gst_registry_chunks_load_plugin (l->registry, &tmp, tmp + payload_len, &newplugin)) { /* Got garbage from the child, so fail and trigger replay of plugins */ GST_ERROR_OBJECT (l->registry, "Problems loading plugin details with tag %u from scanner", tag); return FALSE; } newplugin->flags &= ~GST_PLUGIN_FLAG_CACHED; GST_LOG_OBJECT (l->registry, "marking plugin %p as registered as %s", newplugin, newplugin->filename); newplugin->registered = TRUE; /* We got a set of plugin details - remember it for later */ l->got_plugin_details = TRUE; } else if (entry != NULL) { /* Create a blacklist entry for this file to prevent scanning every time */ plugin_loader_create_blacklist_plugin (l, entry); l->got_plugin_details = TRUE; } if (entry != NULL) { g_free (entry->filename); g_slice_free (PendingPluginEntry, entry); } /* Remove the plugin entry we just loaded */ cur = l->pending_plugins; if (cur != NULL) cur = g_list_delete_link (cur, cur); l->pending_plugins = cur; if (cur == NULL) l->pending_plugins_tail = NULL; break; } case PACKET_SYNC: if (l->is_child) { /* Respond with our reply - also a sync */ put_packet (l, PACKET_SYNC, tag, NULL, 0); GST_LOG ("Got SYNC in child - replying"); } else l->rx_got_sync = TRUE; break; case PACKET_VERSION: if (l->is_child) { /* Respond with our reply - a version packet, with the version */ const gint version_len = sizeof (guint32) + GST_MAGIC_BINARY_VERSION_LEN; guint8 version_info[sizeof (guint32) + GST_MAGIC_BINARY_VERSION_LEN]; memset (version_info, 0, version_len); GST_WRITE_UINT32_BE (version_info, loader_protocol_version); memcpy (version_info + sizeof (guint32), GST_MAGIC_BINARY_VERSION_STR, strlen (GST_MAGIC_BINARY_VERSION_STR)); put_packet (l, PACKET_VERSION, tag, version_info, version_len); GST_LOG ("Got VERSION in child - replying %u", loader_protocol_version); } else { res = check_protocol_version (l, payload, payload_len); } break; default: return FALSE; /* Invalid packet -> something is wrong */ } return res; }
static GstFlowReturn gst_rtp_asf_pay_handle_packet (GstRtpAsfPay * rtpasfpay, GstBuffer * buffer) { GstRTPBasePayload *rtppay; GstAsfPacketInfo *packetinfo; guint8 flags; guint8 *data; guint32 packet_util_size; guint32 packet_offset; guint32 size_left; GstFlowReturn ret = GST_FLOW_OK; rtppay = GST_RTP_BASE_PAYLOAD (rtpasfpay); packetinfo = &rtpasfpay->packetinfo; if (!gst_asf_parse_packet (buffer, packetinfo, TRUE, rtpasfpay->asfinfo.packet_size)) { GST_ERROR_OBJECT (rtpasfpay, "Error while parsing asf packet"); gst_buffer_unref (buffer); return GST_FLOW_ERROR; } if (packetinfo->packet_size == 0) packetinfo->packet_size = rtpasfpay->asfinfo.packet_size; GST_LOG_OBJECT (rtpasfpay, "Packet size: %" G_GUINT32_FORMAT ", padding: %" G_GUINT32_FORMAT, packetinfo->packet_size, packetinfo->padding); /* update padding field to 0 */ if (packetinfo->padding > 0) { GstAsfPacketInfo info; /* find padding field offset */ guint offset = packetinfo->err_cor_len + 2 + gst_asf_get_var_size_field_len (packetinfo->packet_field_type) + gst_asf_get_var_size_field_len (packetinfo->seq_field_type); buffer = gst_buffer_make_writable (buffer); switch (packetinfo->padd_field_type) { case ASF_FIELD_TYPE_DWORD: gst_buffer_memset (buffer, offset, 0, 4); break; case ASF_FIELD_TYPE_WORD: gst_buffer_memset (buffer, offset, 0, 2); break; case ASF_FIELD_TYPE_BYTE: gst_buffer_memset (buffer, offset, 0, 1); break; case ASF_FIELD_TYPE_NONE: default: break; } gst_asf_parse_packet (buffer, &info, FALSE, 0); } if (packetinfo->padding != 0) packet_util_size = rtpasfpay->asfinfo.packet_size - packetinfo->padding; else packet_util_size = packetinfo->packet_size; packet_offset = 0; while (packet_util_size > 0) { /* Even if we don't fill completely an output buffer we * push it when we add an fragment. Because it seems that * it is not possible to determine where a asf packet * fragment ends inside a rtp packet payload. * This flag tells us to push the packet. */ gboolean force_push = FALSE; GstRTPBuffer rtp = GST_RTP_BUFFER_INIT; /* we have no output buffer pending, create one */ if (rtpasfpay->current == NULL) { GST_LOG_OBJECT (rtpasfpay, "Creating new output buffer"); rtpasfpay->current = gst_rtp_buffer_new_allocate_len (GST_RTP_BASE_PAYLOAD_MTU (rtpasfpay), 0, 0); rtpasfpay->cur_off = 0; rtpasfpay->has_ts = FALSE; rtpasfpay->marker = FALSE; } gst_rtp_buffer_map (rtpasfpay->current, GST_MAP_READWRITE, &rtp); data = gst_rtp_buffer_get_payload (&rtp); data += rtpasfpay->cur_off; size_left = gst_rtp_buffer_get_payload_len (&rtp) - rtpasfpay->cur_off; GST_DEBUG_OBJECT (rtpasfpay, "Input buffer bytes consumed: %" G_GUINT32_FORMAT "/%" G_GSIZE_FORMAT, packet_offset, gst_buffer_get_size (buffer)); GST_DEBUG_OBJECT (rtpasfpay, "Output rtpbuffer status"); GST_DEBUG_OBJECT (rtpasfpay, "Current offset: %" G_GUINT32_FORMAT, rtpasfpay->cur_off); GST_DEBUG_OBJECT (rtpasfpay, "Size left: %" G_GUINT32_FORMAT, size_left); GST_DEBUG_OBJECT (rtpasfpay, "Has ts: %s", rtpasfpay->has_ts ? "yes" : "no"); if (rtpasfpay->has_ts) { GST_DEBUG_OBJECT (rtpasfpay, "Ts: %" G_GUINT32_FORMAT, rtpasfpay->ts); } flags = 0; if (packetinfo->has_keyframe) { flags = flags | 0x80; } flags = flags | 0x20; /* Relative timestamp is present */ if (!rtpasfpay->has_ts) { /* this is the first asf packet, its send time is the * rtp packet timestamp */ rtpasfpay->has_ts = TRUE; rtpasfpay->ts = packetinfo->send_time; } if (size_left >= packet_util_size + 8) { /* enough space for the rest of the packet */ if (packet_offset == 0) { flags = flags | 0x40; GST_WRITE_UINT24_BE (data + 1, packet_util_size); } else { GST_WRITE_UINT24_BE (data + 1, packet_offset); force_push = TRUE; } data[0] = flags; GST_WRITE_UINT32_BE (data + 4, (gint32) (packetinfo->send_time) - (gint32) rtpasfpay->ts); gst_buffer_extract (buffer, packet_offset, data + 8, packet_util_size); /* updating status variables */ rtpasfpay->cur_off += 8 + packet_util_size; size_left -= packet_util_size + 8; packet_offset += packet_util_size; packet_util_size = 0; rtpasfpay->marker = TRUE; } else { /* fragment packet */ data[0] = flags; GST_WRITE_UINT24_BE (data + 1, packet_offset); GST_WRITE_UINT32_BE (data + 4, (gint32) (packetinfo->send_time) - (gint32) rtpasfpay->ts); gst_buffer_extract (buffer, packet_offset, data + 8, size_left - 8); /* updating status variables */ rtpasfpay->cur_off += size_left; packet_offset += size_left - 8; packet_util_size -= size_left - 8; size_left = 0; force_push = TRUE; } /* there is not enough room for any more buffers */ if (force_push || size_left <= 8) { gst_rtp_buffer_set_ssrc (&rtp, rtppay->current_ssrc); gst_rtp_buffer_set_marker (&rtp, rtpasfpay->marker); gst_rtp_buffer_set_payload_type (&rtp, GST_RTP_BASE_PAYLOAD_PT (rtppay)); gst_rtp_buffer_set_seq (&rtp, rtppay->seqnum + 1); gst_rtp_buffer_set_timestamp (&rtp, packetinfo->send_time); gst_rtp_buffer_unmap (&rtp); /* trim remaining bytes not used */ if (size_left != 0) { gst_buffer_set_size (rtpasfpay->current, gst_buffer_get_size (rtpasfpay->current) - size_left); } GST_BUFFER_TIMESTAMP (rtpasfpay->current) = GST_BUFFER_TIMESTAMP (buffer); rtppay->seqnum++; rtppay->timestamp = packetinfo->send_time; GST_DEBUG_OBJECT (rtpasfpay, "Pushing rtp buffer"); ret = gst_rtp_base_payload_push (rtppay, rtpasfpay->current); rtpasfpay->current = NULL; if (ret != GST_FLOW_OK) { gst_buffer_unref (buffer); return ret; } } } gst_buffer_unref (buffer); return ret; }
static GstFlowReturn gst_rdt_depay_handle_data (GstRDTDepay * rdtdepay, GstClockTime outtime, GstRDTPacket * packet) { GstFlowReturn ret; GstBuffer *outbuf; GstMapInfo outmap; guint8 *data, *outdata; guint size; guint16 stream_id; guint32 timestamp; gint gap; guint16 seqnum; guint8 flags; guint16 outflags; /* get pointers to the packet data */ data = gst_rdt_packet_data_map (packet, &size); outbuf = gst_buffer_new_and_alloc (12 + size); GST_BUFFER_TIMESTAMP (outbuf) = outtime; GST_DEBUG_OBJECT (rdtdepay, "have size %u", size); /* copy over some things */ stream_id = gst_rdt_packet_data_get_stream_id (packet); timestamp = gst_rdt_packet_data_get_timestamp (packet); flags = gst_rdt_packet_data_get_flags (packet); seqnum = gst_rdt_packet_data_get_seq (packet); GST_DEBUG_OBJECT (rdtdepay, "stream_id %u, timestamp %u, seqnum %d, flags %d", stream_id, timestamp, seqnum, flags); if (rdtdepay->next_seqnum != -1) { gap = gst_rdt_buffer_compare_seqnum (seqnum, rdtdepay->next_seqnum); /* if we have no gap, all is fine */ if (G_UNLIKELY (gap != 0)) { GST_LOG_OBJECT (rdtdepay, "got packet %u, expected %u, gap %d", seqnum, rdtdepay->next_seqnum, gap); if (gap < 0) { /* seqnum > next_seqnum, we are missing some packets, this is always a * DISCONT. */ GST_LOG_OBJECT (rdtdepay, "%d missing packets", gap); rdtdepay->discont = TRUE; } else { /* seqnum < next_seqnum, we have seen this packet before or the sender * could be restarted. If the packet is not too old, we throw it away as * a duplicate, otherwise we mark discont and continue. 100 misordered * packets is a good threshold. See also RFC 4737. */ if (gap < 100) goto dropping; GST_LOG_OBJECT (rdtdepay, "%d > 100, packet too old, sender likely restarted", gap); rdtdepay->discont = TRUE; } } } rdtdepay->next_seqnum = (seqnum + 1); if (rdtdepay->next_seqnum == 0xff00) rdtdepay->next_seqnum = 0; if ((flags & 1) == 0) outflags = 2; else outflags = 0; gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE); outdata = outmap.data; GST_WRITE_UINT16_BE (outdata + 0, 0); /* version */ GST_WRITE_UINT16_BE (outdata + 2, size + 12); /* length */ GST_WRITE_UINT16_BE (outdata + 4, stream_id); /* stream */ GST_WRITE_UINT32_BE (outdata + 6, timestamp); /* timestamp */ GST_WRITE_UINT16_BE (outdata + 10, outflags); /* flags */ memcpy (outdata + 12, data, size); gst_buffer_unmap (outbuf, &outmap); gst_buffer_resize (outbuf, 0, 12 + size); gst_rdt_packet_data_unmap (packet); GST_DEBUG_OBJECT (rdtdepay, "Pushing packet, outtime %" GST_TIME_FORMAT, GST_TIME_ARGS (outtime)); ret = gst_rdt_depay_push (rdtdepay, outbuf); return ret; /* ERRORS */ dropping: { GST_WARNING_OBJECT (rdtdepay, "%d <= 100, dropping old packet", gap); return GST_FLOW_OK; } }
static GstFlowReturn gst_rtp_j2k_depay_flush_tile (GstBaseRTPDepayload * depayload) { GstRtpJ2KDepay *rtpj2kdepay; guint avail, mh_id; GList *packets, *walk; guint8 end[2]; GstFlowReturn ret = GST_FLOW_OK; rtpj2kdepay = GST_RTP_J2K_DEPAY (depayload); /* flush pending PU */ gst_rtp_j2k_depay_flush_pu (depayload); /* take all available buffers */ avail = gst_adapter_available (rtpj2kdepay->t_adapter); if (avail == 0) goto done; mh_id = rtpj2kdepay->last_mh_id; GST_DEBUG_OBJECT (rtpj2kdepay, "flushing tile of size %u", avail); if (gst_adapter_available (rtpj2kdepay->f_adapter) == 0) { GstBuffer *mheader; /* we need a header now */ if ((mheader = rtpj2kdepay->MH[mh_id]) == NULL) goto waiting_header; /* push header in the adapter */ GST_DEBUG_OBJECT (rtpj2kdepay, "pushing header %u", mh_id); gst_adapter_push (rtpj2kdepay->f_adapter, gst_buffer_ref (mheader)); } /* check for last bytes */ gst_adapter_copy (rtpj2kdepay->t_adapter, end, avail - 2, 2); /* now append the tile packets to the frame */ packets = gst_adapter_take_list (rtpj2kdepay->t_adapter, avail); for (walk = packets; walk; walk = g_list_next (walk)) { GstBuffer *buf = GST_BUFFER_CAST (walk->data); if (walk == packets) { guint8 *data; guint size; /* first buffer should contain the SOT */ data = GST_BUFFER_DATA (buf); size = GST_BUFFER_SIZE (buf); if (size < 12) goto invalid_tile; if (data[0] == 0xff && data[1] == J2K_MARKER_SOT) { guint Psot, nPsot; if (end[0] == 0xff && end[1] == J2K_MARKER_EOC) nPsot = avail - 2; else nPsot = avail; Psot = GST_READ_UINT32_BE (&data[6]); if (Psot != nPsot && Psot != 0) { /* Psot must match the size of the tile */ GST_DEBUG_OBJECT (rtpj2kdepay, "set Psot from %u to %u", Psot, nPsot); buf = gst_buffer_make_writable (buf); data = GST_BUFFER_DATA (buf); GST_WRITE_UINT32_BE (&data[6], nPsot); } } } GST_DEBUG_OBJECT (rtpj2kdepay, "append pu packet of size %u", GST_BUFFER_SIZE (buf)); gst_adapter_push (rtpj2kdepay->f_adapter, buf); } g_list_free (packets); done: rtpj2kdepay->last_tile = -1; return ret; /* errors */ waiting_header: { GST_DEBUG_OBJECT (rtpj2kdepay, "waiting for header %u", mh_id); gst_adapter_clear (rtpj2kdepay->t_adapter); rtpj2kdepay->last_tile = -1; return ret; } invalid_tile: { GST_ELEMENT_WARNING (rtpj2kdepay, STREAM, DECODE, ("Invalid tile"), (NULL)); gst_adapter_clear (rtpj2kdepay->t_adapter); rtpj2kdepay->last_tile = -1; return ret; } }
static GstFlowReturn gst_geometric_transform_transform_frame (GstVideoFilter * vfilter, GstVideoFrame * in_frame, GstVideoFrame * out_frame) { GstGeometricTransform *gt; GstGeometricTransformClass *klass; gint x, y; GstFlowReturn ret = GST_FLOW_OK; gdouble *ptr; guint8 *in_data; guint8 *out_data; gt = GST_GEOMETRIC_TRANSFORM_CAST (vfilter); klass = GST_GEOMETRIC_TRANSFORM_GET_CLASS (gt); in_data = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0); out_data = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0); if (GST_VIDEO_FRAME_FORMAT (out_frame) == GST_VIDEO_FORMAT_AYUV) { /* in AYUV black is not just all zeros: * 0x10 is black for Y, * 0x80 is black for Cr and Cb */ for (int i = 0; i < out_frame->map[0].size; i += 4) GST_WRITE_UINT32_BE (out_data + i, 0xff108080); } else { memset (out_data, 0, out_frame->map[0].size); } GST_OBJECT_LOCK (gt); if (gt->precalc_map) { if (gt->needs_remap) { if (klass->prepare_func) if (!klass->prepare_func (gt)) { ret = FALSE; goto end; } gst_geometric_transform_generate_map (gt); } g_return_val_if_fail (gt->map, GST_FLOW_ERROR); ptr = gt->map; for (y = 0; y < gt->height; y++) { for (x = 0; x < gt->width; x++) { /* do the mapping */ gst_geometric_transform_do_map (gt, in_data, out_data, x, y, ptr[0], ptr[1]); ptr += 2; } } } else { for (y = 0; y < gt->height; y++) { for (x = 0; x < gt->width; x++) { gdouble in_x, in_y; if (klass->map_func (gt, x, y, &in_x, &in_y)) { gst_geometric_transform_do_map (gt, in_data, out_data, x, y, in_x, in_y); } else { GST_WARNING_OBJECT (gt, "Failed to do mapping for %d %d", x, y); ret = GST_FLOW_ERROR; goto end; } } } } end: GST_OBJECT_UNLOCK (gt); return ret; }