ID3 refactoring to match apple's player behavior #67
This commit is contained in:
parent
b946ad9234
commit
71f918c01b
@ -25,7 +25,7 @@ import com.google.android.exoplayer.demo.full.player.DemoPlayer;
|
||||
import com.google.android.exoplayer.demo.full.player.DemoPlayer.RendererBuilder;
|
||||
import com.google.android.exoplayer.demo.full.player.HlsRendererBuilder;
|
||||
import com.google.android.exoplayer.demo.full.player.SmoothStreamingRendererBuilder;
|
||||
import com.google.android.exoplayer.metadata.Metadata;
|
||||
import com.google.android.exoplayer.metadata.TxxxMetadata;
|
||||
import com.google.android.exoplayer.text.CaptionStyleCompat;
|
||||
import com.google.android.exoplayer.text.SubtitleView;
|
||||
import com.google.android.exoplayer.util.Util;
|
||||
@ -56,7 +56,7 @@ import android.widget.PopupMenu;
|
||||
import android.widget.PopupMenu.OnMenuItemClickListener;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* An activity that plays media using {@link DemoPlayer}.
|
||||
@ -415,10 +415,13 @@ public class FullPlayerActivity extends Activity implements SurfaceHolder.Callba
|
||||
// DemoPlayer.MetadataListener implementation
|
||||
|
||||
@Override
|
||||
public void onMetadata(List<Metadata> metadata) {
|
||||
public void onMetadata(Map<String, Object> metadata) {
|
||||
for (int i = 0; i < metadata.size(); i++) {
|
||||
Metadata next = metadata.get(i);
|
||||
Log.i(TAG, "ID3 TimedMetadata: key=" + next.key + ", value=" + next.value);
|
||||
if (metadata.containsKey(TxxxMetadata.TYPE)) {
|
||||
TxxxMetadata txxxMetadata = (TxxxMetadata) metadata.get(TxxxMetadata.TYPE);
|
||||
Log.i(TAG, String.format("ID3 TimedMetadata: description=%s, value=%s",
|
||||
txxxMetadata.description, txxxMetadata.value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,6 @@ import com.google.android.exoplayer.TrackRenderer;
|
||||
import com.google.android.exoplayer.chunk.ChunkSampleSource;
|
||||
import com.google.android.exoplayer.chunk.MultiTrackChunkSource;
|
||||
import com.google.android.exoplayer.drm.StreamingDrmSessionManager;
|
||||
import com.google.android.exoplayer.metadata.Metadata;
|
||||
import com.google.android.exoplayer.metadata.MetadataTrackRenderer;
|
||||
import com.google.android.exoplayer.text.TextTrackRenderer;
|
||||
import com.google.android.exoplayer.upstream.DefaultBandwidthMeter;
|
||||
@ -38,7 +37,7 @@ import android.os.Looper;
|
||||
import android.view.Surface;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
@ -141,7 +140,7 @@ public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventLi
|
||||
* A listener for receiving metadata parsed from the media stream.
|
||||
*/
|
||||
public interface MetadataListener {
|
||||
void onMetadata(List<Metadata> metadata);
|
||||
void onMetadata(Map<String, Object> metadata);
|
||||
}
|
||||
|
||||
// Constants pulled into this class for convenience.
|
||||
@ -475,7 +474,7 @@ public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventLi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMetadata(List<Metadata> metadata) {
|
||||
public void onMetadata(Map<String, Object> metadata) {
|
||||
if (metadataListener != null) {
|
||||
metadataListener.onMetadata(metadata);
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ public class HlsRendererBuilder implements RendererBuilder, ManifestCallback<Hls
|
||||
DataSource dataSource = new UriDataSource(userAgent, null);
|
||||
HlsChunkSource chunkSource = new HlsChunkSource(dataSource, manifest);
|
||||
HlsSampleSource sampleSource = new HlsSampleSource(chunkSource, loadControl,
|
||||
VIDEO_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, true, 2);
|
||||
VIDEO_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, true, 3);
|
||||
MediaCodecVideoTrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(sampleSource,
|
||||
MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, 0, player.getMainHandler(), player, 50);
|
||||
MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource);
|
||||
|
@ -20,9 +20,9 @@ import com.google.android.exoplayer.parser.ts.BitsArray;
|
||||
import com.google.android.exoplayer.util.MimeTypes;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Extracts individual TXXX text frames from raw ID3 data.
|
||||
@ -35,12 +35,12 @@ public class Id3Parser implements MetadataParser {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Metadata> parse(byte[] data, int size)
|
||||
public Map<String, Object> parse(byte[] data, int size)
|
||||
throws UnsupportedEncodingException, ParserException {
|
||||
BitsArray id3Buffer = new BitsArray(data, size);
|
||||
int id3Size = parseId3Header(id3Buffer);
|
||||
|
||||
List<Metadata> metadata = new ArrayList<Metadata>();
|
||||
Map<String, Object> metadata = new HashMap<String, Object>();
|
||||
|
||||
while (id3Size > 0) {
|
||||
int frameId0 = id3Buffer.readUnsignedByte();
|
||||
@ -63,20 +63,23 @@ public class Id3Parser implements MetadataParser {
|
||||
id3Buffer.readBytes(frame, 0, frameSize - 1);
|
||||
|
||||
int firstZeroIndex = indexOf(frame, 0, (byte) 0);
|
||||
String key = new String(frame, 0, firstZeroIndex, charset);
|
||||
String description = new String(frame, 0, firstZeroIndex, charset);
|
||||
int valueStartIndex = indexOfNot(frame, firstZeroIndex, (byte) 0);
|
||||
int valueEndIndex = indexOf(frame, valueStartIndex, (byte) 0);
|
||||
String value = new String(frame, valueStartIndex, valueEndIndex - valueStartIndex,
|
||||
charset);
|
||||
metadata.add(new Metadata(key, value));
|
||||
metadata.put(TxxxMetadata.TYPE, new TxxxMetadata(description, value));
|
||||
} else {
|
||||
id3Buffer.skipBytes(frameSize);
|
||||
String type = String.format("%c%c%c%c", frameId0, frameId1, frameId2, frameId3);
|
||||
byte[] frame = new byte[frameSize];
|
||||
id3Buffer.readBytes(frame, 0, frameSize);
|
||||
metadata.put(type, frame);
|
||||
}
|
||||
|
||||
id3Size -= frameSize + 10 /* header size */;
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(metadata);
|
||||
return Collections.unmodifiableMap(metadata);
|
||||
}
|
||||
|
||||
private static int indexOf(byte[] data, int fromIndex, byte key) {
|
||||
|
@ -16,7 +16,7 @@
|
||||
package com.google.android.exoplayer.metadata;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Parses {@link Metadata}s from binary data.
|
||||
@ -32,14 +32,14 @@ public interface MetadataParser {
|
||||
public boolean canParse(String mimeType);
|
||||
|
||||
/**
|
||||
* Parses a list of {@link Metadata} objects from the provided binary data.
|
||||
* Parses a map of metadata type to metadata objects from the provided binary data.
|
||||
*
|
||||
* @param data The raw binary data from which to parse the metadata.
|
||||
* @param size The size of the input data.
|
||||
* @return A parsed {@link List} of {@link Metadata} objects.
|
||||
* @return A parsed {@link Map} of metadata type to metadata objects.
|
||||
* @throws IOException If a problem occurred parsing the data.
|
||||
*/
|
||||
public List<Metadata> parse(byte[] data, int size)
|
||||
public Map<String, Object> parse(byte[] data, int size)
|
||||
throws IOException;
|
||||
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ import android.os.Looper;
|
||||
import android.os.Message;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A {@link TrackRenderer} for metadata embedded in a media stream.
|
||||
@ -45,7 +45,7 @@ public class MetadataTrackRenderer extends TrackRenderer implements Callback {
|
||||
*
|
||||
* @param metadata The metadata to process.
|
||||
*/
|
||||
void onMetadata(List<Metadata> metadata);
|
||||
void onMetadata(Map<String, Object> metadata);
|
||||
|
||||
}
|
||||
|
||||
@ -63,7 +63,7 @@ public class MetadataTrackRenderer extends TrackRenderer implements Callback {
|
||||
private boolean inputStreamEnded;
|
||||
|
||||
private long pendingMetadataTimestamp;
|
||||
private List<Metadata> pendingMetadata;
|
||||
private Map<String, Object> pendingMetadata;
|
||||
|
||||
/**
|
||||
* @param source A source from which samples containing metadata can be read.
|
||||
@ -185,7 +185,7 @@ public class MetadataTrackRenderer extends TrackRenderer implements Callback {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void invokeRenderer(List<Metadata> metadata) {
|
||||
private void invokeRenderer(Map<String, Object> metadata) {
|
||||
if (metadataHandler != null) {
|
||||
metadataHandler.obtainMessage(MSG_INVOKE_RENDERER, metadata).sendToTarget();
|
||||
} else {
|
||||
@ -198,13 +198,13 @@ public class MetadataTrackRenderer extends TrackRenderer implements Callback {
|
||||
public boolean handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_INVOKE_RENDERER:
|
||||
invokeRendererInternal((List<Metadata>) msg.obj);
|
||||
invokeRendererInternal((Map<String, Object>) msg.obj);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void invokeRendererInternal(List<Metadata> metadata) {
|
||||
private void invokeRendererInternal(Map<String, Object> metadata) {
|
||||
metadataRenderer.onMetadata(metadata);
|
||||
}
|
||||
|
||||
|
@ -16,15 +16,18 @@
|
||||
package com.google.android.exoplayer.metadata;
|
||||
|
||||
/**
|
||||
* A metadata that contains textual data associated with time indices.
|
||||
* A metadata that contains parsed ID3 TXXX (User defined text information) frame data associated
|
||||
* with time indices.
|
||||
*/
|
||||
public class Metadata {
|
||||
public class TxxxMetadata {
|
||||
|
||||
public final String key;
|
||||
public static final String TYPE = "TXXX";
|
||||
|
||||
public final String description;
|
||||
public final String value;
|
||||
|
||||
public Metadata(String key, String value) {
|
||||
this.key = key;
|
||||
public TxxxMetadata(String description, String value) {
|
||||
this.description = description;
|
||||
this.value = value;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user