/** * gst_audio_format_fill_silence: * @info: a #GstAudioFormatInfo * @dest: (array length=length) (element-type guint8): a destination * to fill * @length: the length to fill * * Fill @length bytes in @dest with silence samples for @info. */ void gst_audio_format_fill_silence (const GstAudioFormatInfo * info, gpointer dest, gsize length) { guint8 *dptr = dest; g_return_if_fail (info != NULL); g_return_if_fail (dest != NULL); if (info->flags & GST_AUDIO_FORMAT_FLAG_FLOAT || info->flags & GST_AUDIO_FORMAT_FLAG_SIGNED) { /* float or signed always 0 */ orc_memset (dest, 0, length); } else { gint i, j, bps = info->width >> 3; switch (bps) { case 1: orc_memset (dest, info->silence[0], length); break; case 2:{ #if G_BYTE_ORDER == G_LITTLE_ENDIAN guint16 silence = GST_READ_UINT16_LE (info->silence); #else guint16 silence = GST_READ_UINT16_BE (info->silence); #endif audio_orc_splat_u16 (dest, silence, length / bps); break; } case 4:{ #if G_BYTE_ORDER == G_LITTLE_ENDIAN guint32 silence = GST_READ_UINT32_LE (info->silence); #else guint32 silence = GST_READ_UINT32_BE (info->silence); #endif audio_orc_splat_u32 (dest, silence, length / bps); break; } case 8:{ #if G_BYTE_ORDER == G_LITTLE_ENDIAN guint64 silence = GST_READ_UINT64_LE (info->silence); #else guint64 silence = GST_READ_UINT64_BE (info->silence); #endif audio_orc_splat_u64 (dest, silence, length / bps); break; } default: for (i = 0; i < length; i += bps) { for (j = 0; j < bps; j++) *dptr++ = info->silence[j]; } break; } } }
/** * gst_net_time_packet_new: * @buffer: (array): a buffer from which to construct the packet, or NULL * * Creates a new #GstNetTimePacket from a buffer received over the network. The * caller is responsible for ensuring that @buffer is at least * #GST_NET_TIME_PACKET_SIZE bytes long. * * If @buffer is %NULL, the local and remote times will be set to * #GST_CLOCK_TIME_NONE. * * MT safe. Caller owns return value (gst_net_time_packet_free to free). * * Returns: The new #GstNetTimePacket. */ GstNetTimePacket * gst_net_time_packet_new (const guint8 * buffer) { GstNetTimePacket *ret; g_assert (sizeof (GstClockTime) == 8); ret = g_new0 (GstNetTimePacket, 1); if (buffer) { ret->local_time = GST_READ_UINT64_BE (buffer); ret->remote_time = GST_READ_UINT64_BE (buffer + sizeof (GstClockTime)); } else { ret->local_time = GST_CLOCK_TIME_NONE; ret->remote_time = GST_CLOCK_TIME_NONE; } return ret; }
/** * gst_rtp_hdrext_get_ntp_64: * @data: the data to read from * @size: the size of @data * @ntptime: the result NTP time * * Reads the NTP time from the @size NTP-64 extension bytes in @data and store the * result in @ntptime. * * Returns: %TRUE on success. */ gboolean gst_rtp_hdrext_get_ntp_64 (gpointer data, guint size, guint64 * ntptime) { g_return_val_if_fail (data != NULL, FALSE); g_return_val_if_fail (size >= GST_RTP_HDREXT_NTP_64_SIZE, FALSE); if (ntptime) *ntptime = GST_READ_UINT64_BE (data); return TRUE; }
static gboolean moov_recov_parse_buffer_entry (MoovRecovFile * moovrf, TrakBufferEntryInfo * b) { guint8 data[TRAK_BUFFER_ENTRY_INFO_SIZE]; gint read; read = fread (data, 1, TRAK_BUFFER_ENTRY_INFO_SIZE, moovrf->file); if (read != TRAK_BUFFER_ENTRY_INFO_SIZE) return FALSE; b->track_id = GST_READ_UINT32_BE (data); b->nsamples = GST_READ_UINT32_BE (data + 4); b->delta = GST_READ_UINT32_BE (data + 8); b->size = GST_READ_UINT32_BE (data + 12); b->chunk_offset = GST_READ_UINT64_BE (data + 16); b->sync = data[24] != 0; b->do_pts = data[25] != 0; b->pts_offset = GST_READ_UINT64_BE (data + 26); return TRUE; }
static void do_ntp_time (GstClockTime buffer_time, gint segment_start, gint segment_base) { GstSegment segment; GstBuffer *buffer; GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT; guint8 *data; guint64 expected_ntp_time; guint64 timestamp; /* create a segment that controls the behavior * by changing segment.start and segment.base we affect the stream time and * running time respectively */ gst_segment_init (&segment, GST_FORMAT_TIME); segment.start = segment_start; segment.base = segment_base; gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)); expected_ntp_time = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, buffer_time); expected_ntp_time += NTP_OFFSET; expected_ntp_time = gst_util_uint64_scale (expected_ntp_time, (G_GINT64_CONSTANT (1) << 32), GST_SECOND); buffer = create_rtp_buffer (buffer_time, FALSE); fail_unless_equals_int (gst_pad_push (mysrcpad, buffer), GST_FLOW_OK); fail_unless_equals_int (g_list_length (buffers), 1); buffer = g_list_last (buffers)->data; /* get the extension header */ fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READWRITE, &rtpbuffer)); fail_unless (gst_rtp_buffer_get_extension_data (&rtpbuffer, NULL, (gpointer) & data, NULL)); /* ...and read the NTP timestamp and verify that it's the expected one */ timestamp = GST_READ_UINT64_BE (data); fail_unless_equals_uint64 (timestamp, expected_ntp_time); gst_rtp_buffer_unmap (&rtpbuffer); gst_check_drop_buffers (); }
/* SMPTE 377M 11.1 */ gboolean mxf_random_index_pack_parse (const MXFUL * key, const guint8 * data, guint size, GArray ** array) { guint len, i; MXFRandomIndexPackEntry entry; g_return_val_if_fail (data != NULL, FALSE); g_return_val_if_fail (array != NULL, FALSE); if (size < 4) return FALSE; if ((size - 4) % 12 != 0) return FALSE; GST_DEBUG ("Parsing random index pack:"); len = (size - 4) / 12; GST_DEBUG (" number of entries = %u", len); *array = g_array_sized_new (FALSE, FALSE, sizeof (MXFRandomIndexPackEntry), len); for (i = 0; i < len; i++) { entry.body_sid = GST_READ_UINT32_BE (data); entry.offset = GST_READ_UINT64_BE (data + 4); data += 12; GST_DEBUG (" entry %u = body sid %u at offset %" G_GUINT64_FORMAT, i, entry.body_sid, entry.offset); g_array_append_val (*array, entry); } return TRUE; }
/* SMPTE 377M 10.2.3 */ gboolean mxf_index_table_segment_parse (const MXFUL * key, MXFIndexTableSegment * segment, const MXFPrimerPack * primer, const guint8 * data, guint size) { #ifndef GST_DISABLE_GST_DEBUG gchar str[48]; #endif guint16 tag, tag_size; const guint8 *tag_data; g_return_val_if_fail (key != NULL, FALSE); g_return_val_if_fail (data != NULL, FALSE); g_return_val_if_fail (primer != NULL, FALSE); memset (segment, 0, sizeof (MXFIndexTableSegment)); if (size < 70) return FALSE; GST_DEBUG ("Parsing index table segment:"); while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) { if (tag_size == 0 || tag == 0x0000) goto next; switch (tag) { case 0x3c0a: if (tag_size != 16) goto error; memcpy (&segment->instance_id, tag_data, 16); GST_DEBUG (" instance id = %s", mxf_ul_to_string (&segment->instance_id, str)); break; case 0x3f0b: if (!mxf_fraction_parse (&segment->index_edit_rate, tag_data, tag_size)) goto error; GST_DEBUG (" index edit rate = %d/%d", segment->index_edit_rate.n, segment->index_edit_rate.d); break; case 0x3f0c: if (tag_size != 8) goto error; segment->index_start_position = GST_READ_UINT64_BE (tag_data); GST_DEBUG (" index start position = %" G_GINT64_FORMAT, segment->index_start_position); break; case 0x3f0d: if (tag_size != 8) goto error; segment->index_duration = GST_READ_UINT64_BE (tag_data); GST_DEBUG (" index duration = %" G_GINT64_FORMAT, segment->index_duration); break; case 0x3f05: if (tag_size != 4) goto error; segment->edit_unit_byte_count = GST_READ_UINT32_BE (tag_data); GST_DEBUG (" edit unit byte count = %u", segment->edit_unit_byte_count); break; case 0x3f06: if (tag_size != 4) goto error; segment->index_sid = GST_READ_UINT32_BE (tag_data); GST_DEBUG (" index sid = %u", segment->index_sid); break; case 0x3f07: if (tag_size != 4) goto error; segment->body_sid = GST_READ_UINT32_BE (tag_data); GST_DEBUG (" body sid = %u", segment->body_sid); break; case 0x3f08: if (tag_size != 1) goto error; segment->slice_count = GST_READ_UINT8 (tag_data); GST_DEBUG (" slice count = %u", segment->slice_count); break; case 0x3f0e: if (tag_size != 1) goto error; segment->pos_table_count = GST_READ_UINT8 (tag_data); GST_DEBUG (" pos table count = %u", segment->pos_table_count); break; case 0x3f09:{ guint len, i; if (tag_size < 8) goto error; len = GST_READ_UINT32_BE (tag_data); segment->n_delta_entries = len; GST_DEBUG (" number of delta entries = %u", segment->n_delta_entries); if (len == 0) goto next; tag_data += 4; tag_size -= 4; if (GST_READ_UINT32_BE (tag_data) != 6) goto error; tag_data += 4; tag_size -= 4; if (tag_size < len * 6) goto error; segment->delta_entries = g_new (MXFDeltaEntry, len); for (i = 0; i < len; i++) { GST_DEBUG (" delta entry %u:", i); segment->delta_entries[i].pos_table_index = GST_READ_UINT8 (tag_data); tag_data += 1; tag_size -= 1; GST_DEBUG (" pos table index = %d", segment->delta_entries[i].pos_table_index); segment->delta_entries[i].slice = GST_READ_UINT8 (tag_data); tag_data += 1; tag_size -= 1; GST_DEBUG (" slice = %u", segment->delta_entries[i].slice); segment->delta_entries[i].element_delta = GST_READ_UINT32_BE (tag_data); tag_data += 4; tag_size -= 4; GST_DEBUG (" element delta = %u", segment->delta_entries[i].element_delta); } break; } case 0x3f0a:{ guint len, i, j; if (tag_size < 8) goto error; len = GST_READ_UINT32_BE (tag_data); segment->n_index_entries = len; GST_DEBUG (" number of index entries = %u", segment->n_index_entries); if (len == 0) goto next; tag_data += 4; tag_size -= 4; if (GST_READ_UINT32_BE (tag_data) != (11 + 4 * segment->slice_count + 8 * segment->pos_table_count)) goto error; tag_data += 4; tag_size -= 4; if (tag_size < len * (11 + 4 * segment->slice_count + 8 * segment->pos_table_count)) goto error; segment->index_entries = g_new (MXFIndexEntry, len); for (i = 0; i < len; i++) { MXFIndexEntry *entry = &segment->index_entries[i]; GST_DEBUG (" index entry %u:", i); entry->temporal_offset = GST_READ_UINT8 (tag_data); tag_data += 1; tag_size -= 1; GST_DEBUG (" temporal offset = %d", entry->temporal_offset); entry->key_frame_offset = GST_READ_UINT8 (tag_data); tag_data += 1; tag_size -= 1; GST_DEBUG (" keyframe offset = %d", entry->key_frame_offset); entry->flags = GST_READ_UINT8 (tag_data); tag_data += 1; tag_size -= 1; GST_DEBUG (" flags = 0x%02x", entry->flags); entry->stream_offset = GST_READ_UINT64_BE (tag_data); tag_data += 8; tag_size -= 8; GST_DEBUG (" stream offset = %" G_GUINT64_FORMAT, entry->stream_offset); for (j = 0; j < segment->slice_count; j++) { entry->slice_offset[j] = GST_READ_UINT32_BE (tag_data); tag_data += 4; tag_size -= 4; GST_DEBUG (" slice %u offset = %u", j, entry->slice_offset[j]); } for (j = 0; j < segment->pos_table_count; j++) { mxf_fraction_parse (&entry->pos_table[j], tag_data, tag_size); tag_data += 8; tag_size -= 8; GST_DEBUG (" pos table %u = %d/%d", j, entry->pos_table[j].n, entry->pos_table[j].d); } } break; } default: if (!mxf_local_tag_add_to_hash_table (primer, tag, tag_data, tag_size, &segment->other_tags)) goto error; break; } next: data += 4 + tag_size; size -= 4 + tag_size; } return TRUE; error: GST_ERROR ("Invalid index table segment"); return FALSE; }
/* SMPTE 377M 6.1, Table 2 */ gboolean mxf_partition_pack_parse (const MXFUL * key, MXFPartitionPack * pack, const guint8 * data, guint size) { guint i; #ifndef GST_DISABLE_GST_DEBUG gchar str[48]; #endif g_return_val_if_fail (data != NULL, FALSE); g_return_val_if_fail (size >= 84, FALSE); memset (pack, 0, sizeof (MXFPartitionPack)); GST_DEBUG ("Parsing partition pack:"); if (key->u[13] == 0x02) pack->type = MXF_PARTITION_PACK_HEADER; else if (key->u[13] == 0x03) pack->type = MXF_PARTITION_PACK_BODY; else if (key->u[13] == 0x04) pack->type = MXF_PARTITION_PACK_FOOTER; GST_DEBUG (" type = %s", (pack->type == MXF_PARTITION_PACK_HEADER) ? "header" : (pack->type == MXF_PARTITION_PACK_BODY) ? "body" : "footer"); pack->closed = (key->u[14] == 0x02 || key->u[14] == 0x04); pack->complete = (key->u[14] == 0x03 || key->u[14] == 0x04); GST_DEBUG (" closed = %s, complete = %s", (pack->closed) ? "yes" : "no", (pack->complete) ? "yes" : "no"); pack->major_version = GST_READ_UINT16_BE (data); if (pack->major_version != 1) goto error; data += 2; size -= 2; pack->minor_version = GST_READ_UINT16_BE (data); data += 2; size -= 2; GST_DEBUG (" MXF version = %u.%u", pack->major_version, pack->minor_version); pack->kag_size = GST_READ_UINT32_BE (data); data += 4; size -= 4; GST_DEBUG (" KAG size = %u", pack->kag_size); pack->this_partition = GST_READ_UINT64_BE (data); data += 8; size -= 8; GST_DEBUG (" this partition offset = %" G_GUINT64_FORMAT, pack->this_partition); pack->prev_partition = GST_READ_UINT64_BE (data); data += 8; size -= 8; GST_DEBUG (" previous partition offset = %" G_GUINT64_FORMAT, pack->prev_partition); pack->footer_partition = GST_READ_UINT64_BE (data); data += 8; size -= 8; GST_DEBUG (" footer partition offset = %" G_GUINT64_FORMAT, pack->footer_partition); pack->header_byte_count = GST_READ_UINT64_BE (data); data += 8; size -= 8; GST_DEBUG (" header byte count = %" G_GUINT64_FORMAT, pack->header_byte_count); pack->index_byte_count = GST_READ_UINT64_BE (data); data += 8; size -= 8; pack->index_sid = GST_READ_UINT32_BE (data); data += 4; size -= 4; GST_DEBUG (" index sid = %u, size = %" G_GUINT64_FORMAT, pack->index_sid, pack->index_byte_count); pack->body_offset = GST_READ_UINT64_BE (data); data += 8; size -= 8; pack->body_sid = GST_READ_UINT32_BE (data); data += 4; size -= 4; GST_DEBUG (" body sid = %u, offset = %" G_GUINT64_FORMAT, pack->body_sid, pack->body_offset); memcpy (&pack->operational_pattern, data, 16); data += 16; size -= 16; GST_DEBUG (" operational pattern = %s", mxf_ul_to_string (&pack->operational_pattern, str)); pack->n_essence_containers = GST_READ_UINT32_BE (data); data += 4; size -= 4; GST_DEBUG (" number of essence containers = %u", pack->n_essence_containers); if (GST_READ_UINT32_BE (data) != 16) goto error; data += 4; size -= 4; if (size < 16 * pack->n_essence_containers) goto error; if (pack->n_essence_containers) { pack->essence_containers = g_new (MXFUL, pack->n_essence_containers); for (i = 0; i < pack->n_essence_containers; i++) { memcpy (&pack->essence_containers[i], data + i * 16, 16); GST_DEBUG (" essence container %u = %s", i, mxf_ul_to_string (&pack->essence_containers[i], str)); } } pack->valid = TRUE; return TRUE; error: GST_ERROR ("Invalid partition pack"); mxf_partition_pack_reset (pack); return FALSE; }
/* Callbacks used for websocket clients */ static gboolean try_parse_websocket_fragment (SnraServerClient * client) { guint64 frag_size; gchar *header, *outptr; gchar *mask; gchar *decoded; gsize i, avail; // g_print ("Got %u bytes to parse\n", (guint) client->in_bufavail); if (client->in_bufavail < 2) return FALSE; header = outptr = client->in_bufptr; avail = client->in_bufavail; if (header[0] & 0x80) g_print ("FIN flag. Payload type 0x%x\n", header[0] & 0xf); frag_size = header[1] & 0x7f; outptr += 2; if (frag_size < 126) { avail -= 2; } else if (frag_size == 126) { if (avail < 4) return FALSE; frag_size = GST_READ_UINT16_BE (outptr); outptr += 2; avail -= 8; } else { if (avail < 10) return FALSE; frag_size = GST_READ_UINT64_BE (outptr); outptr += 8; avail -= 8; } if ((header[1] & 0x80) == 0) { /* FIXME: drop the connection */ g_print ("Received packet not masked. Skipping\n"); snra_server_connection_lost (client); goto skip_out; } if (avail < 4 + frag_size) { /* Wait for more data */ return FALSE; } /* Consume the 4 mask bytes */ mask = outptr; outptr += 4; avail -= 4; decoded = g_malloc (frag_size + 1); for (i = 0; i < frag_size; i++) { decoded[i] = outptr[i] ^ mask[i % 4]; } decoded[frag_size] = 0; /* Fire a signal to get this packet processed */ g_signal_emit (client, snra_server_client_signals[MSG_RECEIVED], 0, decoded, (guint64)(frag_size)); g_free (decoded); skip_out: { gsize consumed; outptr += frag_size; consumed = outptr - client->in_bufptr; client->in_bufavail -= consumed; client->in_bufptr = outptr; } return TRUE; }