Skip to content

Commit

Permalink
Merge cleaned version of #1234.
Browse files Browse the repository at this point in the history
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=117224172
  • Loading branch information
ojw28 committed Jun 15, 2016
1 parent 99606f6 commit 9cfff0b
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@
import com.google.android.exoplayer.demo.player.SmoothStreamingSourceBuilder;
import com.google.android.exoplayer.demo.ui.TrackSelectionHelper;
import com.google.android.exoplayer.drm.UnsupportedDrmException;
import com.google.android.exoplayer.metadata.GeobMetadata;
import com.google.android.exoplayer.metadata.PrivMetadata;
import com.google.android.exoplayer.metadata.TxxxMetadata;
import com.google.android.exoplayer.metadata.id3.GeobFrame;
import com.google.android.exoplayer.metadata.id3.Id3Frame;
import com.google.android.exoplayer.metadata.id3.PrivFrame;
import com.google.android.exoplayer.metadata.id3.TxxxFrame;
import com.google.android.exoplayer.text.CaptionStyleCompat;
import com.google.android.exoplayer.text.Cue;
import com.google.android.exoplayer.text.SubtitleLayout;
Expand Down Expand Up @@ -67,7 +68,6 @@
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.util.List;
import java.util.Map;

/**
* An activity that plays media using {@link DemoPlayer}.
Expand Down Expand Up @@ -447,23 +447,21 @@ public void onCues(List<Cue> cues) {
// DemoPlayer.MetadataListener implementation

@Override
public void onId3Metadata(Map<String, Object> metadata) {
for (Map.Entry<String, Object> entry : metadata.entrySet()) {
if (TxxxMetadata.TYPE.equals(entry.getKey())) {
TxxxMetadata txxxMetadata = (TxxxMetadata) entry.getValue();
Log.i(TAG, String.format("ID3 TimedMetadata %s: description=%s, value=%s",
TxxxMetadata.TYPE, txxxMetadata.description, txxxMetadata.value));
} else if (PrivMetadata.TYPE.equals(entry.getKey())) {
PrivMetadata privMetadata = (PrivMetadata) entry.getValue();
Log.i(TAG, String.format("ID3 TimedMetadata %s: owner=%s",
PrivMetadata.TYPE, privMetadata.owner));
} else if (GeobMetadata.TYPE.equals(entry.getKey())) {
GeobMetadata geobMetadata = (GeobMetadata) entry.getValue();
public void onId3Metadata(List<Id3Frame> id3Frames) {
for (Id3Frame id3Frame : id3Frames) {
if (id3Frame instanceof TxxxFrame) {
TxxxFrame txxxFrame = (TxxxFrame) id3Frame;
Log.i(TAG, String.format("ID3 TimedMetadata %s: description=%s, value=%s", txxxFrame.id,
txxxFrame.description, txxxFrame.value));
} else if (id3Frame instanceof PrivFrame) {
PrivFrame privFrame = (PrivFrame) id3Frame;
Log.i(TAG, String.format("ID3 TimedMetadata %s: owner=%s", privFrame.id, privFrame.owner));
} else if (id3Frame instanceof GeobFrame) {
GeobFrame geobFrame = (GeobFrame) id3Frame;
Log.i(TAG, String.format("ID3 TimedMetadata %s: mimeType=%s, filename=%s, description=%s",
GeobMetadata.TYPE, geobMetadata.mimeType, geobMetadata.filename,
geobMetadata.description));
geobFrame.id, geobFrame.mimeType, geobFrame.filename, geobFrame.description));
} else {
Log.i(TAG, String.format("ID3 TimedMetadata %s", entry.getKey()));
Log.i(TAG, String.format("ID3 TimedMetadata %s", id3Frame.id));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@
import com.google.android.exoplayer.dash.DashChunkSource;
import com.google.android.exoplayer.drm.StreamingDrmSessionManager;
import com.google.android.exoplayer.hls.HlsSampleSource;
import com.google.android.exoplayer.metadata.Id3Parser;
import com.google.android.exoplayer.metadata.MetadataTrackRenderer;
import com.google.android.exoplayer.metadata.MetadataTrackRenderer.MetadataRenderer;
import com.google.android.exoplayer.metadata.id3.Id3Frame;
import com.google.android.exoplayer.metadata.id3.Id3Parser;
import com.google.android.exoplayer.text.Cue;
import com.google.android.exoplayer.text.TextRenderer;
import com.google.android.exoplayer.text.TextTrackRenderer;
Expand All @@ -54,7 +55,6 @@

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;

/**
Expand All @@ -66,7 +66,7 @@ public class DemoPlayer implements ExoPlayer.Listener, DefaultTrackSelector.Even
ChunkSampleSource.EventListener, HlsSampleSource.EventListener,
DefaultBandwidthMeter.EventListener, MediaCodecVideoTrackRenderer.EventListener,
MediaCodecAudioTrackRenderer.EventListener, StreamingDrmSessionManager.EventListener,
DashChunkSource.EventListener, TextRenderer, MetadataRenderer<Map<String, Object>>,
DashChunkSource.EventListener, TextRenderer, MetadataRenderer<List<Id3Frame>>,
DebugTextViewHelper.Provider {

/**
Expand Down Expand Up @@ -140,7 +140,7 @@ public interface CaptionListener {
* A listener for receiving ID3 metadata parsed from the media stream.
*/
public interface Id3MetadataListener {
void onId3Metadata(Map<String, Object> metadata);
void onId3Metadata(List<Id3Frame> id3Frames);
}

// Constants pulled into this class for convenience.
Expand Down Expand Up @@ -187,8 +187,8 @@ public DemoPlayer(Context context, SourceBuilder sourceBuilder) {
true, mainHandler, this, AudioCapabilities.getCapabilities(context),
AudioManager.STREAM_MUSIC);
TrackRenderer textRenderer = new TextTrackRenderer(this, mainHandler.getLooper());
MetadataTrackRenderer<Map<String, Object>> id3Renderer = new MetadataTrackRenderer<>(
new Id3Parser(), this, mainHandler.getLooper());
MetadataTrackRenderer<List<Id3Frame>> id3Renderer = new MetadataTrackRenderer<>(new Id3Parser(),
this, mainHandler.getLooper());
TrackRenderer[] renderers = new TrackRenderer[] {videoRenderer, audioRenderer, textRenderer,
id3Renderer};

Expand Down Expand Up @@ -434,9 +434,9 @@ public void onCues(List<Cue> cues) {
}

@Override
public void onMetadata(Map<String, Object> metadata) {
public void onMetadata(List<Id3Frame> id3Frames) {
if (id3MetadataListener != null && trackInfo.getTrackSelection(TYPE_METADATA) != null) {
id3MetadataListener.onId3Metadata(metadata);
id3MetadataListener.onId3Metadata(id3Frames);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer.metadata;
package com.google.android.exoplayer.metadata.id3;

import junit.framework.TestCase;

import java.util.Map;
import java.util.List;

/**
* Test for {@link Id3Parser}
*/
public class Id3ParserTest extends TestCase {

public void testParseTxxxFrames() {
byte[] rawId3 = new byte[] { 73, 68, 51, 4, 0, 0, 0, 0, 0, 41, 84, 88, 88, 88, 0, 0, 0, 31,
byte[] rawId3 = new byte[] {73, 68, 51, 4, 0, 0, 0, 0, 0, 41, 84, 88, 88, 88, 0, 0, 0, 31,
0, 0, 3, 0, 109, 100, 105, 97, 108, 111, 103, 95, 86, 73, 78, 68, 73, 67, 79, 49, 53, 50,
55, 54, 54, 52, 95, 115, 116, 97, 114, 116, 0 };

55, 54, 54, 52, 95, 115, 116, 97, 114, 116, 0};
Id3Parser parser = new Id3Parser();
try {
Map<String, Object> metadata = parser.parse(rawId3, rawId3.length);
assertNotNull(metadata);
assertEquals(1, metadata.size());
TxxxMetadata txxx = (TxxxMetadata) metadata.get(TxxxMetadata.TYPE);
assertNotNull(txxx);
assertEquals("", txxx.description);
assertEquals("mdialog_VINDICO1527664_start", txxx.value);
List<Id3Frame> id3Frames = parser.parse(rawId3, rawId3.length);
assertNotNull(id3Frames);
assertEquals(1, id3Frames.size());
TxxxFrame txxxFrame = (TxxxFrame) id3Frames.get(0);
assertEquals("", txxxFrame.description);
assertEquals("mdialog_VINDICO1527664_start", txxxFrame.value);
} catch (Exception exception) {
fail(exception.getMessage());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer.metadata.id3;

/**
* Binary ID3 frame.
*/
public final class BinaryFrame extends Id3Frame {

public final byte[] data;

public BinaryFrame(String type, byte[] data) {
super(type);
this.data = data;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer.metadata;
package com.google.android.exoplayer.metadata.id3;

/**
* A metadata that contains parsed ID3 GEOB (General Encapsulated Object) frame data associated
* with time indices.
* GEOB (General Encapsulated Object) ID3 frame.
*/
public final class GeobMetadata {
public final class GeobFrame extends Id3Frame {

public static final String TYPE = "GEOB";
public static final String ID = "GEOB";

public final String mimeType;
public final String filename;
public final String description;
public final byte[] data;

public GeobMetadata(String mimeType, String filename, String description, byte[] data) {
public GeobFrame(String mimeType, String filename, String description, byte[] data) {
super(ID);
this.mimeType = mimeType;
this.filename = filename;
this.description = description;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer.metadata.id3;

/**
* Base class for ID3 frames.
*/
public abstract class Id3Frame {

/**
* The frame ID.
*/
public final String id;

public Id3Frame(String id) {
this.id = id;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer.metadata;
package com.google.android.exoplayer.metadata.id3;

import com.google.android.exoplayer.ParserException;
import com.google.android.exoplayer.metadata.MetadataParser;
import com.google.android.exoplayer.util.MimeTypes;
import com.google.android.exoplayer.util.ParsableByteArray;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
* Extracts individual TXXX text frames from raw ID3 data.
*/
public final class Id3Parser implements MetadataParser<Map<String, Object>> {
public final class Id3Parser implements MetadataParser<List<Id3Frame>> {

private static final int ID3_TEXT_ENCODING_ISO_8859_1 = 0;
private static final int ID3_TEXT_ENCODING_UTF_16 = 1;
Expand All @@ -41,9 +42,9 @@ public boolean canParse(String mimeType) {
}

@Override
public Map<String, Object> parse(byte[] data, int size)
throws UnsupportedEncodingException, ParserException {
Map<String, Object> metadata = new HashMap<>();
public List<Id3Frame> parse(byte[] data, int size) throws UnsupportedEncodingException,
ParserException {
List<Id3Frame> id3Frames = new ArrayList<>();
ParsableByteArray id3Data = new ParsableByteArray(data, size);
int id3Size = parseId3Header(id3Data);

Expand All @@ -70,9 +71,8 @@ public Map<String, Object> parse(byte[] data, int size)
String description = new String(frame, 0, firstZeroIndex, charset);
int valueStartIndex = firstZeroIndex + delimiterLength(encoding);
int valueEndIndex = indexOfEOS(frame, valueStartIndex, encoding);
String value = new String(frame, valueStartIndex, valueEndIndex - valueStartIndex,
charset);
metadata.put(TxxxMetadata.TYPE, new TxxxMetadata(description, value));
String value = new String(frame, valueStartIndex, valueEndIndex - valueStartIndex, charset);
id3Frames.add(new TxxxFrame(description, value));
} else if (frameId0 == 'P' && frameId1 == 'R' && frameId2 == 'I' && frameId3 == 'V') {
// Check frame ID == PRIV
byte[] frame = new byte[frameSize];
Expand All @@ -82,7 +82,7 @@ public Map<String, Object> parse(byte[] data, int size)
String owner = new String(frame, 0, firstZeroIndex, "ISO-8859-1");
byte[] privateData = new byte[frameSize - firstZeroIndex - 1];
System.arraycopy(frame, firstZeroIndex + 1, privateData, 0, frameSize - firstZeroIndex - 1);
metadata.put(PrivMetadata.TYPE, new PrivMetadata(owner, privateData));
id3Frames.add(new PrivFrame(owner, privateData));
} else if (frameId0 == 'G' && frameId1 == 'E' && frameId2 == 'O' && frameId3 == 'B') {
// Check frame ID == GEOB
int encoding = id3Data.readUnsignedByte();
Expand All @@ -106,19 +106,18 @@ public Map<String, Object> parse(byte[] data, int size)
byte[] objectData = new byte[objectDataSize];
System.arraycopy(frame, descriptionEndIndex + delimiterLength(encoding), objectData, 0,
objectDataSize);
metadata.put(GeobMetadata.TYPE, new GeobMetadata(mimeType, filename,
description, objectData));
id3Frames.add(new GeobFrame(mimeType, filename, description, objectData));
} else {
String type = String.format(Locale.US, "%c%c%c%c", frameId0, frameId1, frameId2, frameId3);
byte[] frame = new byte[frameSize];
id3Data.readBytes(frame, 0, frameSize);
metadata.put(type, frame);
id3Frames.add(new BinaryFrame(type, frame));
}

id3Size -= frameSize + 10 /* header size */;
}

return Collections.unmodifiableMap(metadata);
return Collections.unmodifiableList(id3Frames);
}

private static int indexOf(byte[] data, int fromIndex, byte key) {
Expand Down Expand Up @@ -150,8 +149,8 @@ private static int indexOfEOS(byte[] data, int fromIndex, int encodingByte) {
}

private static int delimiterLength(int encodingByte) {
return (encodingByte == ID3_TEXT_ENCODING_ISO_8859_1
|| encodingByte == ID3_TEXT_ENCODING_UTF_8) ? 1 : 2;
return (encodingByte == ID3_TEXT_ENCODING_ISO_8859_1 || encodingByte == ID3_TEXT_ENCODING_UTF_8)
? 1 : 2;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer.metadata;
package com.google.android.exoplayer.metadata.id3;

/**
* A metadata that contains parsed ID3 PRIV (Private) frame data associated
* with time indices.
* PRIV (Private) ID3 frame.
*/
public final class PrivMetadata {
public final class PrivFrame extends Id3Frame {

public static final String TYPE = "PRIV";
public static final String ID = "PRIV";

public final String owner;
public final byte[] privateData;

public PrivMetadata(String owner, byte[] privateData) {
public PrivFrame(String owner, byte[] privateData) {
super(ID);
this.owner = owner;
this.privateData = privateData;
}
Expand Down
Loading

0 comments on commit 9cfff0b

Please sign in to comment.