static GstFlowReturn gst_wavenc_write_tags (GstWavEnc * wavenc) { const GstTagList *user_tags; GstTagList *tags; guint size; GstBuffer *buf; GstByteWriter bw; g_return_val_if_fail (wavenc != NULL, GST_FLOW_OK); user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (wavenc)); if ((!wavenc->tags) && (!user_tags)) { GST_DEBUG_OBJECT (wavenc, "have no tags"); return GST_FLOW_OK; } tags = gst_tag_list_merge (user_tags, wavenc->tags, gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (wavenc))); GST_DEBUG_OBJECT (wavenc, "writing tags"); gst_byte_writer_init_with_size (&bw, 1024, FALSE); /* add LIST INFO chunk */ gst_byte_writer_put_data (&bw, (const guint8 *) "LIST", 4); gst_byte_writer_put_uint32_le (&bw, 0); gst_byte_writer_put_data (&bw, (const guint8 *) "INFO", 4); /* add tags */ gst_tag_list_foreach (tags, gst_wavparse_tags_foreach, &bw); /* sets real size of LIST INFO chunk */ size = gst_byte_writer_get_pos (&bw); gst_byte_writer_set_pos (&bw, 4); gst_byte_writer_put_uint32_le (&bw, size - 8); gst_tag_list_unref (tags); buf = gst_byte_writer_reset_and_get_buffer (&bw); wavenc->meta_length += gst_buffer_get_size (buf); return gst_pad_push (wavenc->srcpad, buf); }
static void gst_exif_tag_rewrite_offsets (GstExifWriter * writer, guint32 base_offset) { guint32 offset; GST_LOG ("Rewriting tag entries offsets"); offset = gst_byte_writer_get_size (&writer->tagwriter); while (gst_byte_writer_get_pos (&writer->tagwriter) < gst_byte_writer_get_size (&writer->tagwriter)) { guint16 type = 0; guint32 cur_offset = 0; GstByteReader *reader; gint byte_size = 0; guint32 count = 0; guint16 tag_id = 0; reader = (GstByteReader *) & writer->tagwriter; /* read the type */ if (writer->byte_order == G_LITTLE_ENDIAN) { if (!gst_byte_reader_get_uint16_le (reader, &tag_id)) break; if (!gst_byte_reader_get_uint16_le (reader, &type)) break; if (!gst_byte_reader_get_uint32_le (reader, &count)) break; } else { if (!gst_byte_reader_get_uint16_be (reader, &tag_id)) break; if (!gst_byte_reader_get_uint16_be (reader, &type)) break; if (!gst_byte_reader_get_uint32_be (reader, &count)) break; } switch (type) { case EXIF_TYPE_BYTE: case EXIF_TYPE_ASCII: case EXIF_TYPE_UNDEFINED: byte_size = count; break; case EXIF_TYPE_SHORT: byte_size = count * 2; /* 2 bytes */ break; case EXIF_TYPE_LONG: case EXIF_TYPE_SLONG: byte_size = count * 4; /* 4 bytes */ break; case EXIF_TYPE_RATIONAL: case EXIF_TYPE_SRATIONAL: byte_size = count * 8; /* 8 bytes */ break; default: g_assert_not_reached (); break; } /* adjust the offset if needed */ if (byte_size > 4 || tag_id == EXIF_GPS_IFD_TAG) { if (writer->byte_order == G_LITTLE_ENDIAN) { if (gst_byte_reader_peek_uint32_le (reader, &cur_offset)) { gst_byte_writer_put_uint32_le (&writer->tagwriter, cur_offset + offset + base_offset); } } else { if (gst_byte_reader_peek_uint32_be (reader, &cur_offset)) { gst_byte_writer_put_uint32_be (&writer->tagwriter, cur_offset + offset + base_offset); } } GST_DEBUG ("Rewriting tag offset from %u to (%u + %u + %u) %u", cur_offset, cur_offset, offset, base_offset, cur_offset + offset + base_offset); } else { gst_byte_reader_skip (reader, 4); GST_DEBUG ("No need to rewrite tag offset"); } } }
static gboolean flx_decode_delta_flc (GstFlxDec * flxdec, GstByteReader * reader, GstByteWriter * writer) { guint16 lines, start_l; g_return_val_if_fail (flxdec != NULL, FALSE); g_return_val_if_fail (flxdec->delta_data != NULL, FALSE); /* use last frame for delta */ if (!gst_byte_writer_put_data (writer, flxdec->delta_data, flxdec->size)) goto error; if (!gst_byte_reader_get_uint16_le (reader, &lines)) goto error; if (lines > flxdec->hdr.height) { GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. too many lines."); return FALSE; } start_l = lines; while (lines) { guint16 opcode; if (!gst_byte_writer_set_pos (writer, flxdec->hdr.width * (start_l - lines))) goto error; /* process opcode(s) */ while (TRUE) { if (!gst_byte_reader_get_uint16_le (reader, &opcode)) goto error; if ((opcode & 0xc000) == 0) break; if ((opcode & 0xc000) == 0xc000) { /* line skip count */ gulong skip = (0x10000 - opcode); if (skip > flxdec->hdr.height) { GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. " "skip line count too big."); return FALSE; } start_l += skip; if (!gst_byte_writer_set_pos (writer, gst_byte_writer_get_pos (writer) + flxdec->hdr.width * skip)) goto error; } else { /* last pixel */ if (!gst_byte_writer_set_pos (writer, gst_byte_writer_get_pos (writer) + flxdec->hdr.width)) goto error; if (!gst_byte_writer_put_uint8 (writer, opcode & 0xff)) goto error; } } /* last opcode is the packet count */ GST_LOG_OBJECT (flxdec, "have %d packets", opcode); while (opcode--) { /* skip count */ guint8 skip; gint8 count; if (!gst_byte_reader_get_uint8 (reader, &skip)) goto error; if (!gst_byte_writer_set_pos (writer, gst_byte_writer_get_pos (writer) + skip)) goto error; /* RLE count */ if (!gst_byte_reader_get_int8 (reader, &count)) goto error; if (count < 0) { guint16 x; /* replicate word run */ count = ABS (count); GST_LOG_OBJECT (flxdec, "have replicate run of size %d at offset %d", count, skip); if (skip + count > flxdec->hdr.width) { GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. " "line too long."); return FALSE; } if (!gst_byte_reader_get_uint16_le (reader, &x)) goto error; while (count--) { if (!gst_byte_writer_put_uint16_le (writer, x)) { goto error; } } } else { GST_LOG_OBJECT (flxdec, "have literal run of size %d at offset %d", count, skip); if (skip + count > flxdec->hdr.width) { GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. " "line too long."); return FALSE; } while (count--) { guint16 x; if (!gst_byte_reader_get_uint16_le (reader, &x)) goto error; if (!gst_byte_writer_put_uint16_le (writer, x)) goto error; } } } lines--; } return TRUE; error: GST_ERROR_OBJECT (flxdec, "Failed to decode FLI packet"); return FALSE; }
static gboolean flx_decode_delta_fli (GstFlxDec * flxdec, GstByteReader * reader, GstByteWriter * writer) { guint16 start_line, lines; guint line_start_i; g_return_val_if_fail (flxdec != NULL, FALSE); g_return_val_if_fail (flxdec->delta_data != NULL, FALSE); /* use last frame for delta */ if (!gst_byte_writer_put_data (writer, flxdec->delta_data, flxdec->size)) goto error; if (!gst_byte_reader_get_uint16_le (reader, &start_line)) goto error; if (!gst_byte_reader_get_uint16_le (reader, &lines)) goto error; GST_LOG_OBJECT (flxdec, "height %d start line %d line count %d", flxdec->hdr.height, start_line, lines); if (start_line + lines > flxdec->hdr.height) { GST_ERROR_OBJECT (flxdec, "Invalid FLI packet detected. too many lines."); return FALSE; } line_start_i = flxdec->hdr.width * start_line; if (!gst_byte_writer_set_pos (writer, line_start_i)) goto error; while (lines--) { guint8 packets; /* packet count */ if (!gst_byte_reader_get_uint8 (reader, &packets)) goto error; GST_LOG_OBJECT (flxdec, "have %d packets", packets); while (packets--) { /* skip count */ guint8 skip; gint8 count; if (!gst_byte_reader_get_uint8 (reader, &skip)) goto error; /* skip bytes */ if (!gst_byte_writer_set_pos (writer, gst_byte_writer_get_pos (writer) + skip)) goto error; /* RLE count */ if (!gst_byte_reader_get_int8 (reader, &count)) goto error; if (count < 0) { guint8 x; /* literal run */ count = ABS (count); GST_LOG_OBJECT (flxdec, "have literal run of size %d at offset %d", count, skip); if (skip + count > flxdec->hdr.width) { GST_ERROR_OBJECT (flxdec, "Invalid FLI packet detected. " "line too long."); return FALSE; } if (!gst_byte_reader_get_uint8 (reader, &x)) goto error; if (!gst_byte_writer_fill (writer, x, count)) goto error; } else { const guint8 *data; GST_LOG_OBJECT (flxdec, "have replicate run of size %d at offset %d", count, skip); if (skip + count > flxdec->hdr.width) { GST_ERROR_OBJECT (flxdec, "Invalid FLI packet detected. " "line too long."); return FALSE; } /* replicate run */ if (!gst_byte_reader_get_data (reader, count, &data)) goto error; if (!gst_byte_writer_put_data (writer, data, count)) goto error; } } line_start_i += flxdec->hdr.width; if (!gst_byte_writer_set_pos (writer, line_start_i)) goto error; } return TRUE; error: GST_ERROR_OBJECT (flxdec, "Failed to decode FLI packet"); return FALSE; }