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; }
/** * gst_net_time_packet_serialize: * @packet: the #GstNetTimePacket * * Serialized a #GstNetTimePacket into a newly-allocated sequence of * #GST_NET_TIME_PACKET_SIZE bytes, in network byte order. The value returned is * suitable for passing to write(2) or sendto(2) for communication over the * network. * * MT safe. Caller owns return value (g_free to free). * * Returns: A newly allocated sequence of #GST_NET_TIME_PACKET_SIZE bytes. */ guint8 * gst_net_time_packet_serialize (const GstNetTimePacket * packet) { guint8 *ret; g_assert (sizeof (GstClockTime) == 8); ret = g_new0 (guint8, GST_NET_TIME_PACKET_SIZE); GST_WRITE_UINT64_BE (ret, packet->local_time); GST_WRITE_UINT64_BE (ret + sizeof (GstClockTime), packet->remote_time); return ret; }
static void write_fragment (SnraServerClient * client, gchar * body, gsize len) { gchar header[14]; gsize header_len, i; const guint8 masking = 0x00; // 0x80 to enable masking GIOStatus status; union { gchar bytes[4]; guint32 val; } mask; header[0] = 0x81; header_len = 2; if (len < 126) { header[1] = masking | len; } else if (len < 65536) { header[1] = masking | 126; GST_WRITE_UINT16_BE (header + 2, (guint16) (len)); header_len += 2; } else { header[1] = masking | 127; GST_WRITE_UINT64_BE (header + 2, (guint64) (len)); header_len += 8; } /* Add a random mask word. */ if (masking) { mask.val = g_random_int (); memcpy (header + header_len, mask.bytes, 4); header_len += 4; } /* Write WebSocket frame header */ status = write_to_io_channel (client->io, header, header_len); if (status != G_IO_STATUS_NORMAL) goto done; /* Mask the body, and send it */ if (masking) { if (len > client->out_bufsize) { client->out_bufsize = len; client->out_buf = g_realloc (client->out_buf, client->out_bufsize); } for (i = 0; i < len; i++) { client->out_buf[i] = body[i] ^ mask.bytes[i % 4]; } status = write_to_io_channel (client->io, client->out_buf, len); } else { status = write_to_io_channel (client->io, body, len); } done: if (status != G_IO_STATUS_NORMAL) snra_server_connection_lost (client); }
/** * gst_rtp_hdrext_set_ntp_64: * @data: the data to write to * @size: the size of @data * @ntptime: the NTP time * * Writes the NTP time in @ntptime to the format required for the NTP-64 header * extension. @data must hold at least #GST_RTP_HDREXT_NTP_64_SIZE bytes. * * Returns: %TRUE on success. */ gboolean gst_rtp_hdrext_set_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); GST_WRITE_UINT64_BE (data, ntptime); return TRUE; }
/* Create a copy of @buffer_in having the RTP extension */ static GstBuffer * create_extension_buffer (GstBuffer * buffer_in, gboolean clean_point, gboolean end_contiguous, gboolean discont, guint64 ntp_offset, guint8 cseq) { GstBuffer *buffer_out; GstRTPBuffer rtpbuffer_out = GST_RTP_BUFFER_INIT; guint8 *data; guint8 flags = 0; buffer_out = gst_buffer_copy (buffer_in); fail_unless (gst_rtp_buffer_map (buffer_out, GST_MAP_READWRITE, &rtpbuffer_out)); /* extension */ fail_unless (gst_rtp_buffer_set_extension_data (&rtpbuffer_out, 0xABAC, 3)); fail_unless (gst_rtp_buffer_get_extension (&rtpbuffer_out)); fail_unless (gst_rtp_buffer_get_extension_data (&rtpbuffer_out, NULL, (gpointer) & data, NULL)); /* NTP timestamp */ GST_WRITE_UINT64_BE (data, convert_to_ntp (GST_BUFFER_PTS (buffer_in) + ntp_offset)); /* C E D mbz */ if (clean_point) flags |= (1 << 7); if (end_contiguous) flags |= (1 << 6); if (discont) flags |= (1 << 5); GST_WRITE_UINT8 (data + 8, flags); /* CSeq */ GST_WRITE_UINT8 (data + 9, cseq); memset (data + 10, 0, 4); gst_rtp_buffer_unmap (&rtpbuffer_out); return buffer_out; }
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; }