static void lose_and_recover_test (GstHarness * h, guint16 lost_seq, gconstpointer recbuf, gsize recbuf_size) { guint64 duration = 222222; guint64 timestamp = 111111; GstBuffer *bufout; push_lost_event (h, lost_seq, timestamp, duration, FALSE); bufout = gst_harness_pull (h); fail_unless_equals_int (gst_buffer_get_size (bufout), recbuf_size); fail_unless_equals_int (GST_BUFFER_PTS (bufout), timestamp); fail_unless (gst_buffer_memcmp (bufout, 0, recbuf, recbuf_size) == 0); fail_unless (!GST_BUFFER_FLAG_IS_SET (bufout, GST_RTP_BUFFER_FLAG_REDUNDANT)); gst_buffer_unref (bufout); /* Pushing the next buffer with discont flag set */ bufout = gst_buffer_new (); GST_BUFFER_FLAG_SET (bufout, GST_BUFFER_FLAG_DISCONT); bufout = gst_harness_push_and_pull (h, bufout); /* Checking the flag was unset */ fail_unless (!GST_BUFFER_IS_DISCONT (bufout)); gst_buffer_unref (bufout); }
static const GstCencKeyPair* gst_cenc_decrypt_lookup_key (GstCencDecrypt * self, GstBuffer * kid) { GstMapInfo info; const GstCencKeyPair *kp=NULL; int i; gsize sz; /* GstMapInfo info; gchar *id_string; gst_buffer_map (kid, &info, GST_MAP_READ); id_string = gst_cenc_create_uuid_string (info.data); GST_DEBUG_OBJECT (self, "Looking up key ID: %s", id_string); g_free (id_string); gst_buffer_unmap (kid, &info); */ for (i = 0; kp==NULL && i < self->keys->len; ++i) { const GstCencKeyPair *k; k = g_ptr_array_index (self->keys, i); if(gst_buffer_memcmp (kid, 0, g_bytes_get_data (k->key_id, NULL), KEY_LENGTH)==0){ kp=k; } } if (!kp) { kp = gst_cenc_decrypt_get_key (self, kid); } return kp; }
/* Create new stream from params in caps */ static GstSrtpDecSsrcStream * update_session_stream_from_caps (GstSrtpDec * filter, guint32 ssrc, GstCaps * caps) { GstSrtpDecSsrcStream *stream = NULL; GstSrtpDecSsrcStream *old_stream = NULL; err_status_t err; g_return_val_if_fail (GST_IS_SRTP_DEC (filter), NULL); g_return_val_if_fail (GST_IS_CAPS (caps), NULL); stream = get_stream_from_caps (filter, caps, ssrc); old_stream = find_stream_by_ssrc (filter, ssrc); if (stream && old_stream && stream->rtp_cipher == old_stream->rtp_cipher && stream->rtcp_cipher == old_stream->rtcp_cipher && stream->rtp_auth == old_stream->rtp_auth && stream->rtcp_auth == old_stream->rtcp_auth && stream->key && old_stream->key && gst_buffer_get_size (stream->key) == gst_buffer_get_size (old_stream->key)) { GstMapInfo info; if (gst_buffer_map (old_stream->key, &info, GST_MAP_READ)) { gboolean equal; equal = (gst_buffer_memcmp (stream->key, 0, info.data, info.size) == 0); gst_buffer_unmap (old_stream->key, &info); if (equal) { free_stream (stream); return old_stream; } } } /* Remove existing stream, if any */ gst_srtp_dec_remove_stream (filter, ssrc); if (stream) { /* Create new session stream */ err = init_session_stream (filter, ssrc, stream); if (err != err_status_ok) { if (stream->key) gst_buffer_unref (stream->key); g_slice_free (GstSrtpDecSsrcStream, stream); stream = NULL; } } return stream; }
static GstFlowReturn _sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) { fail_unless_equals_int (gst_buffer_get_size (buffer), sizeof (mxf_essence)); fail_unless (gst_buffer_memcmp (buffer, 0, mxf_essence, sizeof (mxf_essence)) == 0); fail_unless (GST_BUFFER_TIMESTAMP (buffer) == 0); fail_unless (GST_BUFFER_DURATION (buffer) == 200 * GST_MSECOND); gst_buffer_unref (buffer); have_data = TRUE; return GST_FLOW_OK; }
static void check_correct_buffer (guint8 * src_data, guint src_size, guint8 * dst_data, guint dst_size) { GstBuffer *buffer = gst_buffer_new_allocate (NULL, src_size, 0); GstBuffer *newBuffer; GstElement *avisubtitle = setup_avisubtitle (); GstEvent *event; fail_unless (g_list_length (buffers) == 0, "Buffers list needs to be empty"); gst_buffer_fill (buffer, 0, src_data, src_size); fail_unless (gst_element_set_state (avisubtitle, GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, "could not set to playing"); ASSERT_BUFFER_REFCOUNT (buffer, "inbuffer", 1); event = gst_event_new_seek (1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 2 * GST_SECOND, GST_SEEK_TYPE_SET, 5 * GST_SECOND); fail_unless (gst_element_send_event (avisubtitle, event) == FALSE, "Seeking is not possible when there is no buffer yet"); fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK, "not accepted a correct buffer"); /* we gave away our reference to the buffer, don't assume anything */ buffer = NULL; /* a new buffer is created in the list */ fail_unless (g_list_length (buffers) == 1, "No new buffer in the buffers list"); event = gst_event_new_seek (1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 2 * GST_SECOND, GST_SEEK_TYPE_SET, 5 * GST_SECOND); fail_unless (gst_element_send_event (avisubtitle, event) == TRUE, "seeking should be working now"); fail_unless (g_list_length (buffers) == 2, "After seeking we need another buffer in the buffers"); newBuffer = GST_BUFFER (buffers->data); buffers = g_list_remove (buffers, newBuffer); fail_unless (g_list_length (buffers) == 1, "Buffers list needs to be empty"); fail_unless (gst_buffer_get_size (newBuffer) == dst_size, "size of the new buffer is wrong ( %d != %d)", gst_buffer_get_size (newBuffer), dst_size); fail_unless (gst_buffer_memcmp (newBuffer, 0, dst_data, dst_size) == 0, "data of the buffer is not correct"); gst_buffer_unref (newBuffer); /* free the buffer from seeking */ gst_buffer_unref (GST_BUFFER (buffers->data)); buffers = g_list_remove (buffers, buffers->data); fail_unless (gst_element_set_state (avisubtitle, GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); cleanup_avisubtitle (avisubtitle); }
/* * Verify that given buffer contains predefined ADTS frame. */ static void buffer_verify_data (void *buffer, void *user_data) { buffer_verify_data_s *vdata; if (!user_data) { return; } vdata = (buffer_verify_data_s *) user_data; GST_DEBUG ("discard: %d", vdata->discard); if (vdata->discard) { if (ctx_verify_buffer) ctx_verify_buffer (vdata, buffer); vdata->buffer_counter++; vdata->offset_counter += gst_buffer_get_size (buffer); if (vdata->buffer_counter == vdata->discard) { vdata->buffer_counter = 0; vdata->discard = 0; } return; } if (!ctx_verify_buffer || !ctx_verify_buffer (vdata, buffer)) { fail_unless (gst_buffer_get_size (buffer) == vdata->data_to_verify_size); fail_unless (gst_buffer_memcmp (buffer, 0, vdata->data_to_verify, vdata->data_to_verify_size) == 0); } if (vdata->buffers_before_offset_skip) { /* This is for skipping the garbage in some test cases */ if (vdata->buffer_counter == vdata->buffers_before_offset_skip) { vdata->offset_counter += vdata->offset_skip_amount; } } if (!vdata->no_metadata) { fail_unless (GST_BUFFER_DTS (buffer) == vdata->ts_counter); fail_unless (GST_BUFFER_DURATION (buffer) != 0); fail_unless (GST_BUFFER_OFFSET (buffer) == vdata->offset_counter); } vdata->ts_counter += GST_BUFFER_DURATION (buffer); vdata->offset_counter += gst_buffer_get_size (buffer); vdata->buffer_counter++; }
static gboolean verify_buffer (buffer_verify_data_s * vdata, GstBuffer * buffer) { guint offset = 0; guint size = 0; if (vdata->data_to_verify == pcap_frame_with_eth_padding) { offset = pcap_frame_with_eth_padding_offset; size = sizeof (pcap_frame_with_eth_padding) - pcap_frame_with_eth_padding_offset - 2; } fail_unless_equals_int (gst_buffer_get_size (buffer), size); fail_unless (gst_buffer_memcmp (buffer, 0, vdata->data_to_verify + offset, size) == 0); return TRUE; }
static gboolean memcmp_buffers (GstBuffer * buf1, GstBuffer * buf2) { gsize size1, size2; gboolean res; GstMapInfo map; size1 = gst_buffer_get_size (buf1); size2 = gst_buffer_get_size (buf2); if (size1 != size2) return FALSE; gst_buffer_map (buf1, &map, GST_MAP_READ); res = gst_buffer_memcmp (buf2, 0, map.data, map.size) == 0; gst_buffer_unmap (buf1, &map); return res; }
static void symmetry_test_assert_passthrough (SymmetryTest * st, GstBuffer * in) { gpointer copy; gsize data_size; GstSample *out; gst_buffer_extract_dup (in, 0, -1, ©, &data_size); fail_unless (gst_app_src_push_buffer (st->sink_src, in) == GST_FLOW_OK); in = NULL; out = gst_app_sink_pull_sample (st->src_sink); fail_unless (out != NULL); fail_unless (gst_buffer_get_size (gst_sample_get_buffer (out)) == data_size); fail_unless (gst_buffer_memcmp (gst_sample_get_buffer (out), 0, copy, data_size) == 0); g_free (copy); gst_sample_unref (out); }
static gboolean gst_mpegv_parse_process_config (GstMpegvParse * mpvparse, GstBuffer * buf, guint size) { guint8 *data; guint8 *data_with_prefix; GstMapInfo map; gint i, offset; if (mpvparse->seq_offset < 4) { /* This shouldn't happen, but just in case... */ GST_WARNING_OBJECT (mpvparse, "Sequence header start code missing."); return FALSE; } gst_buffer_map (buf, &map, GST_MAP_READ); data = map.data + mpvparse->seq_offset; g_assert (size <= map.size); /* pointer to sequence header data including the start code prefix - used for codec private data */ data_with_prefix = data - 4; /* only do stuff if something new; only compare first 11 bytes, changes in quantiser matrix doesn't matter here. Also changing the matrices in codec_data seems to cause problem with decoders */ if (mpvparse->config && size == gst_buffer_get_size (mpvparse->config) && gst_buffer_memcmp (mpvparse->config, 0, data_with_prefix, MIN (size, 11)) == 0) { gst_buffer_unmap (buf, &map); return TRUE; } if (!gst_mpeg_video_parse_sequence_header (&mpvparse->sequencehdr, data, size - mpvparse->seq_offset, 0)) { GST_DEBUG_OBJECT (mpvparse, "failed to parse config data (size %d) at offset %d", size, mpvparse->seq_offset); gst_buffer_unmap (buf, &map); return FALSE; } GST_LOG_OBJECT (mpvparse, "accepting parsed config size %d", size); /* Set mpeg version, and parse sequence extension */ mpvparse->config_flags = FLAG_NONE; for (i = 0; i < mpvparse->ext_count; ++i) { offset = mpvparse->ext_offsets[i]; mpvparse->config_flags |= FLAG_MPEG2; if (offset < size) { if (gst_mpeg_video_parse_sequence_extension (&mpvparse->sequenceext, map.data, size, offset)) { GST_LOG_OBJECT (mpvparse, "Read Sequence Extension"); mpvparse->config_flags |= FLAG_SEQUENCE_EXT; } else if (gst_mpeg_video_parse_sequence_display_extension (&mpvparse->sequencedispext, map.data, size, offset)) { GST_LOG_OBJECT (mpvparse, "Read Sequence Display Extension"); mpvparse->config_flags |= FLAG_SEQUENCE_DISPLAY_EXT; } } } if (mpvparse->config_flags & FLAG_MPEG2) { /* Update the sequence header based on extensions */ GstMpegVideoSequenceExt *seqext = NULL; GstMpegVideoSequenceDisplayExt *seqdispext = NULL; if (mpvparse->config_flags & FLAG_SEQUENCE_EXT) seqext = &mpvparse->sequenceext; if (mpvparse->config_flags & FLAG_SEQUENCE_DISPLAY_EXT) seqdispext = &mpvparse->sequencedispext; gst_mpeg_video_finalise_mpeg2_sequence_header (&mpvparse->sequencehdr, seqext, seqdispext); } if (mpvparse->fps_num == 0 || mpvparse->fps_den == 0) { mpvparse->fps_num = mpvparse->sequencehdr.fps_n; mpvparse->fps_den = mpvparse->sequencehdr.fps_d; } /* parsing ok, so accept it as new config */ if (mpvparse->config != NULL) gst_buffer_unref (mpvparse->config); mpvparse->config = gst_buffer_new_and_alloc (size); gst_buffer_fill (mpvparse->config, 0, data_with_prefix, size); /* trigger src caps update */ mpvparse->update_caps = TRUE; gst_buffer_unmap (buf, &map); return TRUE; }
static GstFlowReturn gst_flac_tag_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) { GstFlacTag *tag; GstFlowReturn ret; GstMapInfo map; gsize size; ret = GST_FLOW_OK; tag = GST_FLAC_TAG (parent); gst_adapter_push (tag->adapter, buffer); /* Initial state, we don't even know if we are dealing with a flac file */ if (tag->state == GST_FLAC_TAG_STATE_INIT) { GstBuffer *id_buffer; if (gst_adapter_available (tag->adapter) < sizeof (FLAC_MAGIC)) goto cleanup; id_buffer = gst_adapter_take_buffer (tag->adapter, FLAC_MAGIC_SIZE); GST_DEBUG_OBJECT (tag, "looking for " FLAC_MAGIC " identifier"); if (gst_buffer_memcmp (id_buffer, 0, FLAC_MAGIC, FLAC_MAGIC_SIZE) == 0) { GST_DEBUG_OBJECT (tag, "pushing " FLAC_MAGIC " identifier buffer"); ret = gst_pad_push (tag->srcpad, id_buffer); if (ret != GST_FLOW_OK) goto cleanup; tag->state = GST_FLAC_TAG_STATE_METADATA_BLOCKS; } else { /* FIXME: does that work well with FLAC files containing ID3v2 tags ? */ gst_buffer_unref (id_buffer); GST_ELEMENT_ERROR (tag, STREAM, WRONG_TYPE, (NULL), (NULL)); ret = GST_FLOW_ERROR; } } /* The fLaC magic string has been skipped, try to detect the beginning * of a metadata block */ if (tag->state == GST_FLAC_TAG_STATE_METADATA_BLOCKS) { guint type; gboolean is_last; const guint8 *block_header; g_assert (tag->metadata_block_size == 0); g_assert (tag->metadata_last_block == FALSE); /* The header of a flac metadata block is 4 bytes long: * 1st bit: indicates whether this is the last metadata info block * 7 next bits: 4 if vorbis comment block * 24 next bits: size of the metadata to follow (big endian) */ if (gst_adapter_available (tag->adapter) < 4) goto cleanup; block_header = gst_adapter_map (tag->adapter, 4); is_last = ((block_header[0] & 0x80) == 0x80); type = block_header[0] & 0x7F; size = (block_header[1] << 16) | (block_header[2] << 8) | block_header[3]; gst_adapter_unmap (tag->adapter); /* The 4 bytes long header isn't included in the metadata size */ tag->metadata_block_size = size + 4; tag->metadata_last_block = is_last; GST_DEBUG_OBJECT (tag, "got metadata block: %" G_GSIZE_FORMAT " bytes, type %d, " "is vorbiscomment: %d, is last: %d", size, type, (type == 0x04), is_last); /* Metadata blocks of type 4 are vorbis comment blocks */ if (type == 0x04) { tag->state = GST_FLAC_TAG_STATE_VC_METADATA_BLOCK; } else { tag->state = GST_FLAC_TAG_STATE_WRITING_METADATA_BLOCK; } } /* Reads a metadata block */ if ((tag->state == GST_FLAC_TAG_STATE_WRITING_METADATA_BLOCK) || (tag->state == GST_FLAC_TAG_STATE_VC_METADATA_BLOCK)) { GstBuffer *metadata_buffer; if (gst_adapter_available (tag->adapter) < tag->metadata_block_size) goto cleanup; metadata_buffer = gst_adapter_take_buffer (tag->adapter, tag->metadata_block_size); /* clear the is-last flag, as the last metadata block will * be the vorbis comment block which we will build ourselves. */ gst_buffer_map (metadata_buffer, &map, GST_MAP_READWRITE); map.data[0] &= (~0x80); gst_buffer_unmap (metadata_buffer, &map); if (tag->state == GST_FLAC_TAG_STATE_WRITING_METADATA_BLOCK) { GST_DEBUG_OBJECT (tag, "pushing metadata block buffer"); ret = gst_pad_push (tag->srcpad, metadata_buffer); if (ret != GST_FLOW_OK) goto cleanup; } else { tag->vorbiscomment = metadata_buffer; } tag->metadata_block_size = 0; tag->state = GST_FLAC_TAG_STATE_METADATA_NEXT_BLOCK; } /* This state is mainly used to be able to stop as soon as we read * a vorbiscomment block from the flac file if we are in an only output * tags mode */ if (tag->state == GST_FLAC_TAG_STATE_METADATA_NEXT_BLOCK) { /* Check if in the previous iteration we read a vorbis comment metadata * block, and stop now if the user only wants to read tags */ if (tag->vorbiscomment != NULL) { guint8 id_data[4]; /* We found some tags, try to parse them and notify the other elements * that we encountered some tags */ GST_DEBUG_OBJECT (tag, "emitting vorbiscomment tags"); gst_buffer_extract (tag->vorbiscomment, 0, id_data, 4); tag->tags = gst_tag_list_from_vorbiscomment_buffer (tag->vorbiscomment, id_data, 4, NULL); if (tag->tags != NULL) { gst_pad_push_event (tag->srcpad, gst_event_new_tag (gst_tag_list_copy (tag->tags))); } gst_buffer_unref (tag->vorbiscomment); tag->vorbiscomment = NULL; } /* Skip to next state */ if (tag->metadata_last_block == FALSE) { tag->state = GST_FLAC_TAG_STATE_METADATA_BLOCKS; } else { tag->state = GST_FLAC_TAG_STATE_ADD_VORBIS_COMMENT; } } /* Creates a vorbis comment block from the metadata which was set * on the gstreamer element, and add it to the flac stream */ if (tag->state == GST_FLAC_TAG_STATE_ADD_VORBIS_COMMENT) { GstBuffer *buffer; const GstTagList *user_tags; GstTagList *merged_tags; /* merge the tag lists */ user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (tag)); if (user_tags != NULL) { merged_tags = gst_tag_list_merge (user_tags, tag->tags, gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (tag))); } else { merged_tags = gst_tag_list_copy (tag->tags); } if (merged_tags == NULL) { /* If we get a NULL list of tags, we must generate a padding block * which is marked as the last metadata block, otherwise we'll * end up with a corrupted flac file. */ GST_WARNING_OBJECT (tag, "No tags found"); buffer = gst_buffer_new_and_alloc (12); if (buffer == NULL) goto no_buffer; gst_buffer_map (buffer, &map, GST_MAP_WRITE); memset (map.data, 0, map.size); map.data[0] = 0x81; /* 0x80 = Last metadata block, * 0x01 = padding block */ gst_buffer_unmap (buffer, &map); } else { guchar header[4]; guint8 fbit[1]; memset (header, 0, sizeof (header)); header[0] = 0x84; /* 0x80 = Last metadata block, * 0x04 = vorbiscomment block */ buffer = gst_tag_list_to_vorbiscomment_buffer (merged_tags, header, sizeof (header), NULL); GST_DEBUG_OBJECT (tag, "Writing tags %" GST_PTR_FORMAT, merged_tags); gst_tag_list_free (merged_tags); if (buffer == NULL) goto no_comment; size = gst_buffer_get_size (buffer); if ((size < 4) || ((size - 4) > 0xFFFFFF)) goto comment_too_long; fbit[0] = 1; /* Get rid of the framing bit at the end of the vorbiscomment buffer * if it exists since libFLAC seems to lose sync because of this * bit in gstflacdec */ if (gst_buffer_memcmp (buffer, size - 1, fbit, 1) == 0) { buffer = gst_buffer_make_writable (buffer); gst_buffer_resize (buffer, 0, size - 1); } } /* The 4 byte metadata block header isn't accounted for in the total * size of the metadata block */ gst_buffer_map (buffer, &map, GST_MAP_WRITE); map.data[1] = (((map.size - 4) & 0xFF0000) >> 16); map.data[2] = (((map.size - 4) & 0x00FF00) >> 8); map.data[3] = ((map.size - 4) & 0x0000FF); gst_buffer_unmap (buffer, &map); GST_DEBUG_OBJECT (tag, "pushing %" G_GSIZE_FORMAT " byte vorbiscomment " "buffer", map.size); ret = gst_pad_push (tag->srcpad, buffer); if (ret != GST_FLOW_OK) { goto cleanup; } tag->state = GST_FLAC_TAG_STATE_AUDIO_DATA; }
gboolean gst_opus_header_is_header (GstBuffer * buf, const char *magic, guint magic_size) { return (gst_buffer_get_size (buf) >= magic_size && !gst_buffer_memcmp (buf, 0, magic, magic_size)); }
static gboolean verify_buffer (buffer_verify_data_s * vdata, GstBuffer * buffer) { if (vdata->discard) { /* check separate header NALs */ gint i = vdata->buffer_counter; guint ofs; /* SEI with start code prefix with 2 0-bytes */ ofs = i == 1; fail_unless (i <= 2); fail_unless (gst_buffer_get_size (buffer) == ctx_headers[i].size - ofs); fail_unless (gst_buffer_memcmp (buffer, 0, ctx_headers[i].data + ofs, gst_buffer_get_size (buffer)) == 0); } else { GstMapInfo map; gst_buffer_map (buffer, &map, GST_MAP_READ); fail_unless (map.size > 4); /* only need to check avc and bs-to-nal output case */ if (GST_READ_UINT24_BE (map.data) == 0x01) { /* in bs-to-nal, a leading 0x00 is stripped from output */ fail_unless (gst_buffer_get_size (buffer) == vdata->data_to_verify_size - 1); fail_unless (gst_buffer_memcmp (buffer, 0, vdata->data_to_verify + 1, vdata->data_to_verify_size - 1) == 0); gst_buffer_unmap (buffer, &map); return TRUE; } else if (GST_READ_UINT32_BE (map.data) == 0x01) { /* this is not avc, use default tests from parser.c */ gst_buffer_unmap (buffer, &map); return FALSE; } /* header is merged in initial frame */ if (vdata->buffer_counter == 0) { guint8 *data = map.data; fail_unless (map.size == vdata->data_to_verify_size + ctx_headers[0].size + ctx_headers[1].size + ctx_headers[2].size); fail_unless (GST_READ_UINT32_BE (data) == ctx_headers[0].size - 4); fail_unless (memcmp (data + 4, ctx_headers[0].data + 4, ctx_headers[0].size - 4) == 0); data += ctx_headers[0].size; fail_unless (GST_READ_UINT32_BE (data) == ctx_headers[1].size - 4); fail_unless (memcmp (data + 4, ctx_headers[1].data + 4, ctx_headers[1].size - 4) == 0); data += ctx_headers[1].size; fail_unless (GST_READ_UINT32_BE (data) == ctx_headers[2].size - 4); fail_unless (memcmp (data + 4, ctx_headers[2].data + 4, ctx_headers[2].size - 4) == 0); data += ctx_headers[2].size; fail_unless (GST_READ_UINT32_BE (data) == vdata->data_to_verify_size - 4); fail_unless (memcmp (data + 4, vdata->data_to_verify + 4, vdata->data_to_verify_size - 4) == 0); } else { fail_unless (GST_READ_UINT32_BE (map.data) == map.size - 4); fail_unless (map.size == vdata->data_to_verify_size); fail_unless (memcmp (map.data + 4, vdata->data_to_verify + 4, map.size - 4) == 0); } gst_buffer_unmap (buffer, &map); return TRUE; } return FALSE; }
static gboolean gst_mpegv_parse_process_config (GstMpegvParse * mpvparse, GstMapInfo * info, guint size) { GstMpegVideoPacket packet; guint8 *data_with_prefix; gint i; if (mpvparse->seq_offset < 4) { /* This shouldn't happen, but just in case... */ GST_WARNING_OBJECT (mpvparse, "Sequence header start code missing."); return FALSE; } packet.data = info->data; packet.type = GST_MPEG_VIDEO_PACKET_SEQUENCE; packet.offset = mpvparse->seq_offset; packet.size = size - mpvparse->seq_offset; /* pointer to sequence header data including the start code prefix - used for codec private data */ data_with_prefix = (guint8 *) packet.data + packet.offset - 4; /* only do stuff if something new; only compare first 8 bytes, changes in quantiser matrix or bitrate don't matter here. Also changing the matrices in codec_data seems to cause problem with decoders */ if (mpvparse->config && gst_buffer_memcmp (mpvparse->config, 0, data_with_prefix, MIN (size, 8)) == 0) { return TRUE; } if (!gst_mpeg_video_packet_parse_sequence_header (&packet, &mpvparse->sequencehdr)) { GST_DEBUG_OBJECT (mpvparse, "failed to parse config data (size %d) at offset %d", size, mpvparse->seq_offset); return FALSE; } mpvparse->seqhdr_updated = TRUE; GST_LOG_OBJECT (mpvparse, "accepting parsed config size %d", size); /* Set mpeg version, and parse sequence extension */ mpvparse->config_flags = FLAG_NONE; for (i = 0; i < mpvparse->ext_count; ++i) { packet.type = GST_MPEG_VIDEO_PACKET_EXTENSION; packet.offset = mpvparse->ext_offsets[i]; packet.size = (gint) size - mpvparse->ext_offsets[i]; mpvparse->config_flags |= FLAG_MPEG2; if (packet.size > 1) { switch (packet.data[packet.offset] >> 4) { case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE: if (gst_mpeg_video_packet_parse_sequence_extension (&packet, &mpvparse->sequenceext)) { GST_LOG_OBJECT (mpvparse, "Read Sequence Extension"); mpvparse->config_flags |= FLAG_SEQUENCE_EXT; mpvparse->seqext_updated = TRUE; } break; case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY: if (gst_mpeg_video_packet_parse_sequence_display_extension (&packet, &mpvparse->sequencedispext)) { GST_LOG_OBJECT (mpvparse, "Read Sequence Display Extension"); mpvparse->config_flags |= FLAG_SEQUENCE_DISPLAY_EXT; mpvparse->seqdispext_updated = TRUE; } break; case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX: if (gst_mpeg_video_packet_parse_quant_matrix_extension (&packet, &mpvparse->quantmatrext)) { GST_LOG_OBJECT (mpvparse, "Read Quantization Matrix Extension"); mpvparse->quantmatrext_updated = TRUE; } break; } } } if (mpvparse->config_flags & FLAG_MPEG2) { /* Update the sequence header based on extensions */ GstMpegVideoSequenceExt *seqext = NULL; GstMpegVideoSequenceDisplayExt *seqdispext = NULL; if (mpvparse->config_flags & FLAG_SEQUENCE_EXT) seqext = &mpvparse->sequenceext; if (mpvparse->config_flags & FLAG_SEQUENCE_DISPLAY_EXT) seqdispext = &mpvparse->sequencedispext; gst_mpeg_video_finalise_mpeg2_sequence_header (&mpvparse->sequencehdr, seqext, seqdispext); } if (mpvparse->fps_num == 0 || mpvparse->fps_den == 0) { mpvparse->fps_num = mpvparse->sequencehdr.fps_n; mpvparse->fps_den = mpvparse->sequencehdr.fps_d; } /* parsing ok, so accept it as new config */ if (mpvparse->config != NULL) gst_buffer_unref (mpvparse->config); mpvparse->config = gst_buffer_new_and_alloc (size); gst_buffer_fill (mpvparse->config, 0, data_with_prefix, size); /* trigger src caps update */ mpvparse->update_caps = TRUE; return TRUE; }