Merge cleaned version of https://github.com/google/ExoPlayer/pull/1234.
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=117224172
This commit is contained in:
parent
99606f6e2e
commit
9cfff0b028
@ -30,9 +30,10 @@ import com.google.android.exoplayer.demo.player.HlsSourceBuilder;
|
||||
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;
|
||||
@ -67,7 +68,6 @@ import java.net.CookieHandler;
|
||||
import java.net.CookieManager;
|
||||
import java.net.CookiePolicy;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* An activity that plays media using {@link DemoPlayer}.
|
||||
@ -447,23 +447,21 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,9 +34,10 @@ import com.google.android.exoplayer.chunk.ChunkSampleSource;
|
||||
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;
|
||||
@ -54,7 +55,6 @@ import android.view.Surface;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
@ -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 {
|
||||
|
||||
/**
|
||||
@ -140,7 +140,7 @@ public class DemoPlayer implements ExoPlayer.Listener, DefaultTrackSelector.Even
|
||||
* 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.
|
||||
@ -187,8 +187,8 @@ public class DemoPlayer implements ExoPlayer.Listener, DefaultTrackSelector.Even
|
||||
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};
|
||||
|
||||
@ -434,9 +434,9 @@ public class DemoPlayer implements ExoPlayer.Listener, DefaultTrackSelector.Even
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,11 +13,11 @@
|
||||
* 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}
|
||||
@ -25,19 +25,17 @@ import java.util.Map;
|
||||
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());
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
@ -41,9 +42,9 @@ public final class Id3Parser implements MetadataParser<Map<String, Object>> {
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
@ -70,9 +71,8 @@ public final class Id3Parser implements MetadataParser<Map<String, Object>> {
|
||||
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];
|
||||
@ -82,7 +82,7 @@ public final class Id3Parser implements MetadataParser<Map<String, Object>> {
|
||||
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();
|
||||
@ -106,19 +106,18 @@ public final class Id3Parser implements MetadataParser<Map<String, Object>> {
|
||||
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) {
|
||||
@ -150,8 +149,8 @@ public final class Id3Parser implements MetadataParser<Map<String, Object>> {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
@ -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;
|
||||
}
|
@ -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 TXXX (User defined text information) frame data associated
|
||||
* with time indices.
|
||||
* TXXX (User defined text information) ID3 frame.
|
||||
*/
|
||||
public final class TxxxMetadata {
|
||||
public final class TxxxFrame extends Id3Frame {
|
||||
|
||||
public static final String TYPE = "TXXX";
|
||||
public static final String ID = "TXXX";
|
||||
|
||||
public final String description;
|
||||
public final String value;
|
||||
|
||||
public TxxxMetadata(String description, String value) {
|
||||
public TxxxFrame(String description, String value) {
|
||||
super(ID);
|
||||
this.description = description;
|
||||
this.value = value;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user