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; }
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; }
static GstBuffer * gst_wavenc_create_header_buf (GstWavEnc * wavenc, guint audio_data_size) { struct wave_header wave; GstBuffer *buf; GstMapInfo map; guint8 *header; buf = gst_buffer_new_and_alloc (WAV_HEADER_LEN); gst_buffer_map (buf, &map, GST_MAP_WRITE); header = map.data; memset (header, 0, WAV_HEADER_LEN); wave.common.wChannels = wavenc->channels; wave.common.wBitsPerSample = wavenc->width; wave.common.dwSamplesPerSec = wavenc->rate; /* Fill out our wav-header with some information */ memcpy (wave.riff.id, "RIFF", 4); wave.riff.len = audio_data_size + WAV_HEADER_LEN - 8; memcpy (wave.riff.wav_id, "WAVE", 4); memcpy (wave.format.id, "fmt ", 4); wave.format.len = 16; wave.common.wFormatTag = wavenc->format; wave.common.wBlockAlign = (wavenc->width / 8) * wave.common.wChannels; wave.common.dwAvgBytesPerSec = wave.common.wBlockAlign * wave.common.dwSamplesPerSec; memcpy (wave.data.id, "data", 4); wave.data.len = audio_data_size; memcpy (header, (char *) wave.riff.id, 4); GST_WRITE_UINT32_LE (header + 4, wave.riff.len); memcpy (header + 8, (char *) wave.riff.wav_id, 4); memcpy (header + 12, (char *) wave.format.id, 4); GST_WRITE_UINT32_LE (header + 16, wave.format.len); GST_WRITE_UINT16_LE (header + 20, wave.common.wFormatTag); GST_WRITE_UINT16_LE (header + 22, wave.common.wChannels); GST_WRITE_UINT32_LE (header + 24, wave.common.dwSamplesPerSec); GST_WRITE_UINT32_LE (header + 28, wave.common.dwAvgBytesPerSec); GST_WRITE_UINT16_LE (header + 32, wave.common.wBlockAlign); GST_WRITE_UINT16_LE (header + 34, wave.common.wBitsPerSample); memcpy (header + 36, (char *) wave.data.id, 4); GST_WRITE_UINT32_LE (header + 40, wave.data.len); gst_buffer_unmap (buf, &map); return buf; }
static void gst_mim_enc_create_tcp_header (GstMimEnc * mimenc, guint8 * p, guint32 payload_size, GstClockTime ts, gboolean keyframe, gboolean paused) { p[0] = 24; p[1] = paused ? 1 : 0; GST_WRITE_UINT16_LE (p + 2, mimenc->width); GST_WRITE_UINT16_LE (p + 4, mimenc->height); GST_WRITE_UINT16_LE (p + 6, keyframe ? 1 : 0); GST_WRITE_UINT32_LE (p + 8, payload_size); GST_WRITE_UINT32_LE (p + 12, paused ? 0 : GST_MAKE_FOURCC ('M', 'L', '2', '0')); GST_WRITE_UINT32_LE (p + 16, 0); GST_WRITE_UINT32_LE (p + 20, ts / GST_MSECOND); }
static GstAdapter * create_and_fill_adapter (void) { GstAdapter *adapter; gint i, j; adapter = gst_adapter_new (); fail_unless (adapter != NULL); for (i = 0; i < 10000; i += 4) { GstBuffer *buf = gst_buffer_new_and_alloc (sizeof (guint32) * 4); guint8 *data; fail_unless (buf != NULL); data = GST_BUFFER_DATA (buf); for (j = 0; j < 4; j++) { GST_WRITE_UINT32_LE (data, i + j); data += sizeof (guint32); } gst_adapter_push (adapter, buf); } return adapter; }
static GstAdapter * create_and_fill_adapter (void) { GstAdapter *adapter; gint i, j; adapter = gst_adapter_new (); fail_unless (adapter != NULL); for (i = 0; i < 10000; i += 4) { GstBuffer *buf; GstMapInfo info; guint8 *ptr; buf = gst_buffer_new_and_alloc (sizeof (guint32) * 4); fail_unless (buf != NULL); fail_unless (gst_buffer_map (buf, &info, GST_MAP_WRITE)); ptr = info.data; for (j = 0; j < 4; j++) { GST_WRITE_UINT32_LE (ptr, i + j); ptr += sizeof (guint32); } gst_buffer_unmap (buf, &info); gst_adapter_push (adapter, buf); } return adapter; }
static gboolean gst_wavenc_write_labls (guint8 ** data, GList * list) { GstWavEncLabl *labl; while (list) { labl = list->data; memcpy (*data, (gchar *) labl->chunk_id, 4); GST_WRITE_UINT32_LE (*data + 4, labl->chunk_data_size); GST_WRITE_UINT32_LE (*data + 8, labl->cue_point_id); memcpy (*data + 12, (gchar *) labl->text, strlen (labl->text)); *data += 8 + GST_ROUND_UP_2 (labl->chunk_data_size); list = g_list_next (list); } return TRUE; }
static gboolean gst_wavenc_write_notes (guint8 ** data, GList * list) { GstWavEncNote *note; while (list) { note = list->data; memcpy (*data, (gchar *) note->chunk_id, 4); GST_WRITE_UINT32_LE (*data + 4, note->chunk_data_size); GST_WRITE_UINT32_LE (*data + 8, note->cue_point_id); memcpy (*data + 12, (gchar *) note->text, strlen (note->text)); *data += 8 + GST_ROUND_UP_2 (note->chunk_data_size); list = g_list_next (list); } return TRUE; }
static gboolean gst_wavenc_write_cues (guint8 ** data, GList * list) { GstWavEncCue *cue; while (list) { cue = list->data; GST_WRITE_UINT32_LE (*data, cue->id); GST_WRITE_UINT32_LE (*data + 4, cue->position); memcpy (*data + 8, (gchar *) cue->data_chunk_id, 4); GST_WRITE_UINT32_LE (*data + 12, cue->chunk_start); GST_WRITE_UINT32_LE (*data + 16, cue->block_start); GST_WRITE_UINT32_LE (*data + 20, cue->sample_offset); *data += 24; list = g_list_next (list); } return TRUE; }
static GstBuffer * gst_mimenc_create_tcp_header (GstMimEnc * mimenc, guint32 payload_size, GstClockTime timestamp, gboolean keyframe, gboolean paused) { // 24 bytes GstBuffer *buf_header = gst_buffer_new_and_alloc (24); guchar *p = (guchar *) GST_BUFFER_DATA (buf_header); GST_BUFFER_TIMESTAMP (buf_header) = timestamp; p[0] = 24; p[1] = paused ? 1 : 0; GST_WRITE_UINT16_LE (p + 2, mimenc->width); GST_WRITE_UINT16_LE (p + 4, mimenc->height); GST_WRITE_UINT16_LE (p + 6, keyframe ? 1 : 0); GST_WRITE_UINT32_LE (p + 8, payload_size); GST_WRITE_UINT32_LE (p + 12, paused ? 0 : GST_MAKE_FOURCC ('M', 'L', '2', '0')); GST_WRITE_UINT32_LE (p + 16, 0); GST_WRITE_UINT32_LE (p + 20, timestamp / GST_MSECOND); return buf_header; }
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; }
/* Correctly format samples with width!=depth for the wav format, i.e. * have the data in the highest depth bits and all others zero */ static void gst_wavenc_format_samples (GstBuffer * buf, guint width, guint depth) { guint8 *data = GST_BUFFER_DATA (buf); guint nsamples = (GST_BUFFER_SIZE (buf) * 8) / width; guint32 tmp; for (; nsamples; nsamples--) { switch (width) { case 8: tmp = *data; *data = *data << (width - depth); data += 1; break; case 16: tmp = GST_READ_UINT16_LE (data); tmp = tmp << (width - depth); GST_WRITE_UINT16_LE (data, tmp); data += 2; break; case 24: tmp = READ24_FROM_LE (data); tmp = tmp << (width - depth); WRITE24_TO_LE (data, tmp); data += 3; break; case 32: tmp = GST_READ_UINT32_LE (data); tmp = tmp << (width - depth); GST_WRITE_UINT32_LE (data, tmp); data += 4; break; } } }
static GstFlowReturn gst_wavenc_write_toc (GstWavEnc * wavenc) { GList *list; GstToc *toc; GstTocEntry *entry, *subentry; GstBuffer *buf; GstMapInfo map; guint8 *data; guint32 ncues, size, cues_size, labls_size, notes_size; if (!wavenc->toc) { GST_DEBUG_OBJECT (wavenc, "have no toc, checking toc_setter"); wavenc->toc = gst_toc_setter_get_toc (GST_TOC_SETTER (wavenc)); } if (!wavenc->toc) { GST_WARNING_OBJECT (wavenc, "have no toc"); return GST_FLOW_OK; } toc = gst_toc_ref (wavenc->toc); size = 0; cues_size = 0; labls_size = 0; notes_size = 0; /* check if the TOC entries is valid */ list = gst_toc_get_entries (toc); entry = list->data; if (gst_toc_entry_is_alternative (entry)) { list = gst_toc_entry_get_sub_entries (entry); while (list) { subentry = list->data; if (!gst_toc_entry_is_sequence (subentry)) return FALSE; list = g_list_next (list); } list = gst_toc_entry_get_sub_entries (entry); } if (gst_toc_entry_is_sequence (entry)) { while (list) { entry = list->data; if (!gst_toc_entry_is_sequence (entry)) return FALSE; list = g_list_next (list); } list = gst_toc_get_entries (toc); } ncues = g_list_length (list); GST_DEBUG_OBJECT (wavenc, "number of cue entries: %d", ncues); while (list) { guint32 id = 0; gint64 id64; const gchar *uid; entry = list->data; uid = gst_toc_entry_get_uid (entry); id64 = g_ascii_strtoll (uid, NULL, 0); /* check if id unique compatible with guint32 else generate random */ if (id64 >= 0 && gst_wavenc_is_cue_id_unique (id64, wavenc->cues)) { id = (guint32) id64; } else { do { id = g_random_int (); } while (!gst_wavenc_is_cue_id_unique (id, wavenc->cues)); } gst_wavenc_parse_cue (wavenc, id, entry); gst_wavenc_parse_labl (wavenc, id, entry); gst_wavenc_parse_note (wavenc, id, entry); list = g_list_next (list); } /* count cues size */ if (wavenc->cues) { cues_size = 24 * g_list_length (wavenc->cues); size += 12 + cues_size; } else { GST_WARNING_OBJECT (wavenc, "cue's not found"); return FALSE; } /* count labls size */ if (wavenc->labls) { list = wavenc->labls; while (list) { GstWavEncLabl *labl; labl = list->data; labls_size += 8 + GST_ROUND_UP_2 (labl->chunk_data_size); list = g_list_next (list); } size += labls_size; } /* count notes size */ if (wavenc->notes) { list = wavenc->notes; while (list) { GstWavEncNote *note; note = list->data; notes_size += 8 + GST_ROUND_UP_2 (note->chunk_data_size); list = g_list_next (list); } size += notes_size; } if (wavenc->labls || wavenc->notes) { size += 12; } buf = gst_buffer_new_and_alloc (size); gst_buffer_map (buf, &map, GST_MAP_WRITE); data = map.data; memset (data, 0, size); /* write Cue Chunk */ if (wavenc->cues) { memcpy (data, (gchar *) "cue ", 4); GST_WRITE_UINT32_LE (data + 4, 4 + cues_size); GST_WRITE_UINT32_LE (data + 8, ncues); data += 12; gst_wavenc_write_cues (&data, wavenc->cues); /* write Associated Data List Chunk */ if (wavenc->labls || wavenc->notes) { memcpy (data, (gchar *) "LIST", 4); GST_WRITE_UINT32_LE (data + 4, 4 + labls_size + notes_size); memcpy (data + 8, (gchar *) "adtl", 4); data += 12; if (wavenc->labls) gst_wavenc_write_labls (&data, wavenc->labls); if (wavenc->notes) gst_wavenc_write_notes (&data, wavenc->notes); } } /* free resources */ if (toc) gst_toc_unref (toc); if (wavenc->cues) g_list_free_full (wavenc->cues, g_free); if (wavenc->labls) g_list_free_full (wavenc->labls, g_free); if (wavenc->notes) g_list_free_full (wavenc->notes, g_free); gst_buffer_unmap (buf, &map); wavenc->meta_length += gst_buffer_get_size (buf); return gst_pad_push (wavenc->srcpad, buf); }
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; }
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 GstFlowReturn gst_rtp_asf_pay_handle_packet (GstRtpAsfPay * rtpasfpay, GstBuffer * buffer) { GstBaseRTPPayload *rtppay; GstAsfPacketInfo *packetinfo; guint8 flags; guint8 *data; guint32 packet_util_size; guint32 packet_offset; guint32 size_left; GstFlowReturn ret = GST_FLOW_OK; rtppay = GST_BASE_RTP_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_WRITE_UINT32_LE (&(GST_BUFFER_DATA (buffer)[offset]), 0); break; case ASF_FIELD_TYPE_WORD: GST_WRITE_UINT16_LE (&(GST_BUFFER_DATA (buffer)[offset]), 0); break; case ASF_FIELD_TYPE_BYTE: GST_BUFFER_DATA (buffer)[offset] = 0; 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; /* 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_BASE_RTP_PAYLOAD_MTU (rtpasfpay), 0, 0); rtpasfpay->cur_off = gst_rtp_buffer_get_header_len (rtpasfpay->current); rtpasfpay->has_ts = FALSE; rtpasfpay->marker = FALSE; } data = GST_BUFFER_DATA (rtpasfpay->current) + rtpasfpay->cur_off; size_left = GST_BUFFER_SIZE (rtpasfpay->current) - rtpasfpay->cur_off; GST_DEBUG_OBJECT (rtpasfpay, "Input buffer bytes consumed: %" G_GUINT32_FORMAT "/%" G_GUINT32_FORMAT, packet_offset, GST_BUFFER_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 (GST_BUFFER_SIZE (rtpasfpay->current) - rtpasfpay->cur_off >= 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); memcpy (data + 8, GST_BUFFER_DATA (buffer) + packet_offset, 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); memcpy (data + 8, GST_BUFFER_DATA (buffer) + packet_offset, 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) { if (size_left != 0) { /* trim remaining bytes not used */ GstBuffer *aux = gst_buffer_create_sub (rtpasfpay->current, 0, GST_BUFFER_SIZE (rtpasfpay->current) - size_left); gst_buffer_unref (rtpasfpay->current); rtpasfpay->current = aux; } gst_rtp_buffer_set_ssrc (rtpasfpay->current, rtppay->current_ssrc); gst_rtp_buffer_set_marker (rtpasfpay->current, rtpasfpay->marker); gst_rtp_buffer_set_payload_type (rtpasfpay->current, GST_BASE_RTP_PAYLOAD_PT (rtppay)); gst_rtp_buffer_set_seq (rtpasfpay->current, rtppay->seqnum + 1); gst_rtp_buffer_set_timestamp (rtpasfpay->current, packetinfo->send_time); GST_BUFFER_TIMESTAMP (rtpasfpay->current) = GST_BUFFER_TIMESTAMP (buffer); gst_buffer_set_caps (rtpasfpay->current, GST_PAD_CAPS (GST_BASE_RTP_PAYLOAD_SRCPAD (rtppay))); rtppay->seqnum++; rtppay->timestamp = packetinfo->send_time; GST_DEBUG_OBJECT (rtpasfpay, "Pushing rtp buffer"); ret = gst_pad_push (GST_BASE_RTP_PAYLOAD_SRCPAD (rtppay), rtpasfpay->current); rtpasfpay->current = NULL; if (ret != GST_FLOW_OK) { gst_buffer_unref (buffer); return ret; } } } gst_buffer_unref (buffer); return ret; }
static void fill_bmp_header(guint8 *image_data, guint image_width, guint image_height) { guint dib_image_row_size = ((DIB_BITS_PER_PIXEL * image_width + 31) / 32) * 4; guint dib_image_size = dib_image_row_size * image_height; guint8 *data = image_data; *data = 'B'; data++; *data = 'M'; data++; GST_WRITE_UINT32_LE(data, (BMP_HEADER_SIZE + dib_image_size)); data += 4; GST_WRITE_UINT16_LE(data, BMP_RESERVED); data += 2; GST_WRITE_UINT16_LE(data, BMP_RESERVED); data += 2; GST_WRITE_UINT32_LE(data, BMP_HEADER_SIZE); data += 4; GST_WRITE_UINT32_LE(data, DIB_HEADER_SIZE); data += 4; GST_WRITE_UINT32_LE(data, image_width); data += 4; GST_WRITE_UINT32_LE(data, image_height); data += 4; GST_WRITE_UINT16_LE(data, DIB_COLOR_PLANES); data += 2; GST_WRITE_UINT16_LE(data, DIB_BITS_PER_PIXEL); data += 2; GST_WRITE_UINT32_LE(data, DIB_COMPRESSION); data += 4; GST_WRITE_UINT32_LE(data, dib_image_size); data += 4; GST_WRITE_UINT32_LE(data, DIB_HORIZONTAL_RESOLUTION); data += 4; GST_WRITE_UINT32_LE(data, DIB_VERTICAL_RESOLUTION); data += 4; GST_WRITE_UINT32_LE(data, DIB_COLORS_IN_PALETTE); data += 4; GST_WRITE_UINT32_LE(data, DIB_IMPORTANT_COLORS); data += 4; }
static gboolean gst_rtp_celt_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps) { GstStructure *structure; GstRtpCELTDepay *rtpceltdepay; gint clock_rate, nb_channels = 0, frame_size = 0; GstBuffer *buf; GstMapInfo map; guint8 *ptr; const gchar *params; GstCaps *srccaps; gboolean res; rtpceltdepay = GST_RTP_CELT_DEPAY (depayload); structure = gst_caps_get_structure (caps, 0); if (!gst_structure_get_int (structure, "clock-rate", &clock_rate)) goto no_clockrate; depayload->clock_rate = clock_rate; if ((params = gst_structure_get_string (structure, "encoding-params"))) nb_channels = atoi (params); if (!nb_channels) nb_channels = DEFAULT_CHANNELS; if ((params = gst_structure_get_string (structure, "frame-size"))) frame_size = atoi (params); if (!frame_size) frame_size = DEFAULT_FRAMESIZE; rtpceltdepay->frame_size = frame_size; GST_DEBUG_OBJECT (depayload, "clock-rate=%d channels=%d frame-size=%d", clock_rate, nb_channels, frame_size); /* construct minimal header and comment packet for the decoder */ buf = gst_buffer_new_and_alloc (60); gst_buffer_map (buf, &map, GST_MAP_WRITE); ptr = map.data; memcpy (ptr, "CELT ", 8); ptr += 8; memcpy (ptr, "1.1.12", 7); ptr += 20; GST_WRITE_UINT32_LE (ptr, 0x80000006); /* version */ ptr += 4; GST_WRITE_UINT32_LE (ptr, 56); /* header_size */ ptr += 4; GST_WRITE_UINT32_LE (ptr, clock_rate); /* rate */ ptr += 4; GST_WRITE_UINT32_LE (ptr, nb_channels); /* channels */ ptr += 4; GST_WRITE_UINT32_LE (ptr, frame_size); /* frame-size */ ptr += 4; GST_WRITE_UINT32_LE (ptr, -1); /* overlap */ ptr += 4; GST_WRITE_UINT32_LE (ptr, -1); /* bytes_per_packet */ ptr += 4; GST_WRITE_UINT32_LE (ptr, 0); /* extra headers */ gst_buffer_unmap (buf, &map); srccaps = gst_caps_new_empty_simple ("audio/x-celt"); res = gst_pad_set_caps (depayload->srcpad, srccaps); gst_caps_unref (srccaps); gst_rtp_base_depayload_push (GST_RTP_BASE_DEPAYLOAD (rtpceltdepay), buf); buf = gst_buffer_new_and_alloc (sizeof (gst_rtp_celt_comment)); gst_buffer_fill (buf, 0, gst_rtp_celt_comment, sizeof (gst_rtp_celt_comment)); gst_rtp_base_depayload_push (GST_RTP_BASE_DEPAYLOAD (rtpceltdepay), buf); return res; /* ERRORS */ no_clockrate: { GST_ERROR_OBJECT (depayload, "no clock-rate specified"); return FALSE; } }
static gboolean gst_real_video_dec_setcaps (GstPad * pad, GstCaps * caps) { GstRealVideoDec *dec = GST_REAL_VIDEO_DEC (GST_PAD_PARENT (pad)); GstStructure *s = gst_caps_get_structure (caps, 0); gint version, res, width, height, format, subformat; gint framerate_num, framerate_denom; gchar data[36]; gboolean bres; const GValue *v; if (!gst_structure_get_int (s, "rmversion", &version) || !gst_structure_get_int (s, "width", (gint *) & width) || !gst_structure_get_int (s, "height", (gint *) & height) || !gst_structure_get_int (s, "format", &format) || !gst_structure_get_int (s, "subformat", &subformat) || !gst_structure_get_fraction (s, "framerate", &framerate_num, &framerate_denom)) goto missing_keys; GST_LOG_OBJECT (dec, "Setting version to %d", version); close_library (dec, &dec->lib); if (!open_library (dec, version, &dec->lib)) goto open_failed; /* Initialize REAL driver. */ GST_WRITE_UINT16_LE (data + 0, 11); GST_WRITE_UINT16_LE (data + 2, width); GST_WRITE_UINT16_LE (data + 4, height); GST_WRITE_UINT16_LE (data + 6, 0); GST_WRITE_UINT32_LE (data + 8, 0); GST_WRITE_UINT32_LE (data + 12, subformat); GST_WRITE_UINT32_LE (data + 16, 1); GST_WRITE_UINT32_LE (data + 20, format); if ((res = dec->lib.Init (&data, &dec->lib.context))) goto could_not_initialize; if ((v = gst_structure_get_value (s, "codec_data"))) { GstBuffer *buf; guint32 *msgdata; guint i; guint8 *bufdata; guint bufsize; struct { guint32 type; guint32 msg; gpointer data; guint32 extra[6]; } msg; buf = g_value_peek_pointer (v); bufdata = GST_BUFFER_DATA (buf); bufsize = GST_BUFFER_SIZE (buf); /* skip format and subformat */ bufdata += 8; bufsize -= 8; GST_LOG_OBJECT (dec, "Creating custom message of length %d", bufsize); msgdata = g_new0 (guint32, bufsize + 2); if (!msgdata) goto could_not_allocate; msg.type = 0x24; msg.msg = 1 + ((subformat >> 16) & 7); msg.data = msgdata; for (i = 0; i < 6; i++) msg.extra[i] = 0; msgdata[0] = width; msgdata[1] = height; for (i = 0; i < bufsize; i++) msgdata[i + 2] = 4 * (guint32) bufdata[i]; res = dec->lib.Message (&msg, dec->lib.context); g_free (msgdata); if (res) goto could_not_send_message; }
static gboolean gst_rtp_speex_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps) { GstStructure *structure; GstRtpSPEEXDepay *rtpspeexdepay; gint clock_rate, nb_channels; GstBuffer *buf; GstMapInfo map; guint8 *data; const gchar *params; GstCaps *srccaps; gboolean res; rtpspeexdepay = GST_RTP_SPEEX_DEPAY (depayload); structure = gst_caps_get_structure (caps, 0); if (!gst_structure_get_int (structure, "clock-rate", &clock_rate)) goto no_clockrate; depayload->clock_rate = clock_rate; if (!(params = gst_structure_get_string (structure, "encoding-params"))) nb_channels = 1; else { nb_channels = atoi (params); } /* construct minimal header and comment packet for the decoder */ buf = gst_buffer_new_and_alloc (80); gst_buffer_map (buf, &map, GST_MAP_WRITE); data = map.data; memcpy (data, "Speex ", 8); data += 8; memcpy (data, "1.1.12", 7); data += 20; GST_WRITE_UINT32_LE (data, 1); /* version */ data += 4; GST_WRITE_UINT32_LE (data, 80); /* header_size */ data += 4; GST_WRITE_UINT32_LE (data, clock_rate); /* rate */ data += 4; GST_WRITE_UINT32_LE (data, gst_rtp_speex_depay_get_mode (clock_rate)); /* mode */ data += 4; GST_WRITE_UINT32_LE (data, 4); /* mode_bitstream_version */ data += 4; GST_WRITE_UINT32_LE (data, nb_channels); /* nb_channels */ data += 4; GST_WRITE_UINT32_LE (data, -1); /* bitrate */ data += 4; GST_WRITE_UINT32_LE (data, 0xa0); /* frame_size */ data += 4; GST_WRITE_UINT32_LE (data, 0); /* VBR */ data += 4; GST_WRITE_UINT32_LE (data, 1); /* frames_per_packet */ data += 4; GST_WRITE_UINT32_LE (data, 0); /* extra_headers */ data += 4; GST_WRITE_UINT32_LE (data, 0); /* reserved1 */ data += 4; GST_WRITE_UINT32_LE (data, 0); /* reserved2 */ gst_buffer_unmap (buf, &map); srccaps = gst_caps_new_empty_simple ("audio/x-speex"); res = gst_pad_set_caps (depayload->srcpad, srccaps); gst_caps_unref (srccaps); gst_rtp_base_depayload_push (GST_RTP_BASE_DEPAYLOAD (rtpspeexdepay), buf); buf = gst_buffer_new_and_alloc (sizeof (gst_rtp_speex_comment)); gst_buffer_fill (buf, 0, gst_rtp_speex_comment, sizeof (gst_rtp_speex_comment)); gst_rtp_base_depayload_push (GST_RTP_BASE_DEPAYLOAD (rtpspeexdepay), buf); return res; /* ERRORS */ no_clockrate: { GST_DEBUG_OBJECT (depayload, "no clock-rate specified"); return FALSE; } }
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 gboolean gst_rtp_celt_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps) { GstStructure *structure; GstRtpCELTDepay *rtpceltdepay; gint clock_rate, nb_channels, frame_size; GstBuffer *buf; guint8 *data; const gchar *params; GstCaps *srccaps; gboolean res; rtpceltdepay = GST_RTP_CELT_DEPAY (depayload); structure = gst_caps_get_structure (caps, 0); if (!gst_structure_get_int (structure, "clock-rate", &clock_rate)) goto no_clockrate; depayload->clock_rate = clock_rate; if (!(params = gst_structure_get_string (structure, "encoding-params"))) nb_channels = 1; else { nb_channels = atoi (params); } if (!(params = gst_structure_get_string (structure, "frame-size"))) frame_size = 480; else { frame_size = atoi (params); } /* construct minimal header and comment packet for the decoder */ buf = gst_buffer_new_and_alloc (60); data = GST_BUFFER_DATA (buf); memcpy (data, "CELT ", 8); data += 8; memcpy (data, "1.1.12", 7); data += 20; GST_WRITE_UINT32_LE (data, 0x80000006); /* version */ data += 4; GST_WRITE_UINT32_LE (data, 56); /* header_size */ data += 4; GST_WRITE_UINT32_LE (data, clock_rate); /* rate */ data += 4; GST_WRITE_UINT32_LE (data, nb_channels); /* channels */ data += 4; GST_WRITE_UINT32_LE (data, frame_size); /* frame-size */ data += 4; GST_WRITE_UINT32_LE (data, -1); /* overlap */ data += 4; GST_WRITE_UINT32_LE (data, -1); /* bytes_per_packet */ data += 4; GST_WRITE_UINT32_LE (data, 0); /* extra headers */ srccaps = gst_caps_new_simple ("audio/x-celt", NULL); res = gst_pad_set_caps (depayload->srcpad, srccaps); gst_caps_unref (srccaps); gst_buffer_set_caps (buf, GST_PAD_CAPS (depayload->srcpad)); gst_base_rtp_depayload_push (GST_BASE_RTP_DEPAYLOAD (rtpceltdepay), buf); buf = gst_buffer_new_and_alloc (sizeof (gst_rtp_celt_comment)); memcpy (GST_BUFFER_DATA (buf), gst_rtp_celt_comment, sizeof (gst_rtp_celt_comment)); gst_buffer_set_caps (buf, GST_PAD_CAPS (depayload->srcpad)); gst_base_rtp_depayload_push (GST_BASE_RTP_DEPAYLOAD (rtpceltdepay), buf); return res; /* ERRORS */ no_clockrate: { GST_DEBUG_OBJECT (depayload, "no clock-rate specified"); return FALSE; } }