package serializers.protobuf;
import static serializers.protobuf.media.MediaContentHolder.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import data.media.MediaTransformer;
import serializers.*;
/**
*<p>
* Note on stream test case: as per [http://code.google.com/apis/protocolbuffers/docs/techniques.html]
* we will have to external framing; we just use very simple length prefix, which should work
* reasonably well.
*/
public class Protobuf
{
public static void register(TestGroups groups) {
groups.media.add(new Transformer(), new PBSerializer(),
new SerFeatures(
SerFormat.BIN_CROSSLANG,
SerGraph.FLAT_TREE,
SerClass.CLASSES_KNOWN,
""
)
);
}
// ------------------------------------------------------------
// Serializers
static final class PBSerializer extends Serializer<MediaContent>
{
public String getName() { return "protobuf"; }
@Override
public MediaContent deserialize (byte[] array) throws Exception {
return MediaContent.parseFrom(array);
}
@Override
public byte[] serialize(MediaContent content) {
return content.toByteArray();
}
@Override
public final void serializeItems(MediaContent[] items, OutputStream out0) throws IOException
{
DataOutputStream out = new DataOutputStream(out0);
for (MediaContent item : items) {
byte[] data = item.toByteArray();
out.writeInt(data.length);
out.write(data);
}
// should we write end marker (length of 0) or not? For now, omit it
out.flush();
}
@Override
public MediaContent[] deserializeItems(InputStream in0, int numberOfItems) throws IOException
{
DataInputStream in = new DataInputStream(in0);
MediaContent[] result = new MediaContent[numberOfItems];
for (int i = 0; i < numberOfItems; ++i) {
int len = in.readInt();
byte[] data = new byte[len];
in.readFully(data);
result[i] = MediaContent.parseFrom(data);
}
return result;
}
}
// ------------------------------------------------------------
// Transformers
static final class Transformer extends MediaTransformer<MediaContent>
{
@Override
public MediaContent[] resultArray(int size) { return new MediaContent[size]; }
// ----------------------------------------------------------
// Forward
public MediaContent forward(data.media.MediaContent mc)
{
MediaContent.Builder cb = MediaContent.newBuilder();
cb.setMedia(forwardMedia(mc.media));
for (data.media.Image image : mc.images) {
cb.addImage(forwardImage(image));
}
return cb.build();
}
private Media forwardMedia(data.media.Media media)
{
// Media
Media.Builder mb = Media.newBuilder();
mb.setUri(media.uri);
if (media.title != null) mb.setTitle(media.title);
mb.setWidth(media.width);
mb.setHeight(media.height);
mb.setFormat(media.format);
mb.setDuration(media.duration);
mb.setSize(media.size);
if (media.hasBitrate) mb.setBitrate(media.bitrate);
for (String person : media.persons) {
mb.addPerson(person);
}
mb.setPlayer(forwardPlayer(media.player));
if (media.copyright != null) mb.setCopyright(media.copyright);
return mb.build();
}
public Media.Player forwardPlayer(data.media.Media.Player p)
{
switch (p) {
case JAVA: return Media.Player.JAVA;
case FLASH: return Media.Player.FLASH;
default:
throw new AssertionError("invalid case: " + p);
}
}
private Image forwardImage(data.media.Image image)
{
Image.Builder ib = Image.newBuilder();
ib.setUri(image.uri);
if (image.title != null) ib.setTitle(image.title);
ib.setWidth(image.width);
ib.setHeight(image.height);
ib.setSize(forwardSize(image.size));
return ib.build();
}
public Image.Size forwardSize(data.media.Image.Size s)
{
switch (s) {
case SMALL: return Image.Size.SMALL;
case LARGE: return Image.Size.LARGE;
default:
throw new AssertionError("invalid case: " + s);
}
}
// ----------------------------------------------------------
// Reverse
public data.media.MediaContent reverse(MediaContent mc)
{
List<data.media.Image> images = new ArrayList<data.media.Image>(mc.getImageCount());
for (Image image : mc.getImageList()) {
images.add(reverseImage(image));
}
return new data.media.MediaContent(reverseMedia(mc.getMedia()), images);
}
private data.media.Media reverseMedia(Media media)
{
// Media
return new data.media.Media(
media.getUri(),
media.hasTitle() ? media.getTitle() : null,
media.getWidth(),
media.getHeight(),
media.getFormat(),
media.getDuration(),
media.getSize(),
media.hasBitrate() ? media.getBitrate() : 0,
media.hasBitrate(),
new ArrayList<String>(media.getPersonList()),
reversePlayer(media.getPlayer()),
media.hasCopyright() ? media.getCopyright() : null
);
}
public data.media.Media.Player reversePlayer(Media.Player p)
{
switch (p) {
case JAVA: return data.media.Media.Player.JAVA;
case FLASH: return data.media.Media.Player.FLASH;
default:
throw new AssertionError("invalid case: " + p);
}
}
private data.media.Image reverseImage(Image image)
{
return new data.media.Image(
image.getUri(),
image.hasTitle() ? image.getTitle() : null,
image.getWidth(),
image.getHeight(),
reverseSize(image.getSize()));
}
public data.media.Image.Size reverseSize(Image.Size s)
{
switch (s) {
case SMALL: return data.media.Image.Size.SMALL;
case LARGE: return data.media.Image.Size.LARGE;
default:
throw new AssertionError("invalid case: " + s);
}
}
public data.media.MediaContent shallowReverse(MediaContent mc)
{
return new data.media.MediaContent(reverseMedia(mc.getMedia()), Collections.<data.media.Image>emptyList());
}
}
}