Skip to content

Commit

Permalink
Purely stylistic changes to FLV extractor
Browse files Browse the repository at this point in the history
  • Loading branch information
ojw28 committed Oct 26, 2015
1 parent fb75b65 commit 950cc70
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@
/**
* Parses audio tags of from an FLV stream and extracts AAC frames.
*/
final class AudioTagPayloadReader extends TagPayloadReader {
// Sound format
/* package */ final class AudioTagPayloadReader extends TagPayloadReader {

// Audio format
private static final int AUDIO_FORMAT_AAC = 10;

// AAC PACKET TYPE
Expand All @@ -47,48 +48,40 @@ final class AudioTagPayloadReader extends TagPayloadReader {
private boolean hasParsedAudioDataHeader;
private boolean hasOutputFormat;


public AudioTagPayloadReader(TrackOutput output) {
super(output);
}

@Override
public void seek() {

// Do nothing.
}

@Override
protected boolean parseHeader(ParsableByteArray data) throws UnsupportedTrack {
// Parse audio data header, if it was not done, to extract information
// about the audio codec and audio configuration.
protected boolean parseHeader(ParsableByteArray data) throws UnsupportedFormatException {
// Parse audio data header, if it was not done, to extract information about the audio codec
// and audio configuration.
if (!hasParsedAudioDataHeader) {
int header = data.readUnsignedByte();
int soundFormat = (header >> 4) & 0x0F;
int audioFormat = (header >> 4) & 0x0F;
int sampleRateIndex = (header >> 2) & 0x03;
int bitsPerSample = (header & 0x02) == 0x02 ? 16 : 8;
int channels = (header & 0x01) + 1;

if (sampleRateIndex < 0 || sampleRateIndex >= AUDIO_SAMPLING_RATE_TABLE.length) {
throw new UnsupportedTrack("Invalid sample rate for the audio track");
throw new UnsupportedFormatException("Invalid sample rate for the audio track");
}

if (!hasOutputFormat) {
if (audioFormat != AUDIO_FORMAT_AAC) {
// TODO: Adds support for MP3 and PCM
if (soundFormat != AUDIO_FORMAT_AAC) {
throw new UnsupportedTrack("Audio track not supported. Format: " + soundFormat +
", Sample rate: " + sampleRateIndex + ", bps: " + bitsPerSample + ", channels: " +
channels);
if (audioFormat != AUDIO_FORMAT_AAC) {
throw new UnsupportedFormatException("Audio format not supported: " + audioFormat);
}
}

hasParsedAudioDataHeader = true;
} else {
// Skip header if it was parsed previously.
data.skipBytes(1);
}

// In all the cases we will be managing AAC format (otherwise an exception would be
// fired so we can just always return true
// In all the cases we will be managing AAC format (otherwise an exception would be fired so we
// can just always return true.
return true;
}

Expand All @@ -110,10 +103,9 @@ protected void parsePayload(ParsableByteArray data, long timeUs) {
audioSpecificConfig);

MediaFormat mediaFormat = MediaFormat.createAudioFormat(MediaFormat.NO_VALUE,
MimeTypes.AUDIO_AAC, MediaFormat.NO_VALUE, MediaFormat.NO_VALUE, durationUs,
MimeTypes.AUDIO_AAC, MediaFormat.NO_VALUE, MediaFormat.NO_VALUE, getDurationUs(),
audioParams.second, audioParams.first, Collections.singletonList(audioSpecificConfig),
null);

output.format(mediaFormat);
hasOutputFormat = true;
} else if (packetType == AAC_PACKET_TYPE_AAC_RAW) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public int read(ExtractorInput input, PositionHolder seekPosition) throws IOExce
return readSample(input);
}
}
} catch (AudioTagPayloadReader.UnsupportedTrack unsupportedTrack) {
} catch (AudioTagPayloadReader.UnsupportedFormatException unsupportedTrack) {
unsupportedTrack.printStackTrace();
return RESULT_END_OF_INPUT;
}
Expand Down Expand Up @@ -186,11 +186,11 @@ private boolean readHeader(ExtractorInput input) throws IOException, Interrupted
* @return True if tag header was read successfully. Otherwise, false.
* @throws IOException If an error occurred reading from the source.
* @throws InterruptedException If the thread was interrupted.
* @throws TagPayloadReader.UnsupportedTrack If payload of the tag is using a codec non
* @throws TagPayloadReader.UnsupportedFormatException If payload of the tag is using a codec non
* supported codec.
*/
private boolean readTagHeader(ExtractorInput input) throws IOException, InterruptedException,
TagPayloadReader.UnsupportedTrack {
TagPayloadReader.UnsupportedFormatException {
try {
// skipping previous tag size field
input.skipFully(4);
Expand Down Expand Up @@ -235,11 +235,11 @@ private boolean readTagHeader(ExtractorInput input) throws IOException, Interrup
* @return One of {@link Extractor#RESULT_CONTINUE} and {@link Extractor#RESULT_END_OF_INPUT}.
* @throws IOException If an error occurred reading from the source.
* @throws InterruptedException If the thread was interrupted.
* @throws TagPayloadReader.UnsupportedTrack If payload of the tag is using a codec non
* @throws TagPayloadReader.UnsupportedFormatException If payload of the tag is using a codec non
* supported codec.
*/
private int readSample(ExtractorInput input) throws IOException,
InterruptedException, AudioTagPayloadReader.UnsupportedTrack {
InterruptedException, AudioTagPayloadReader.UnsupportedFormatException {
if (tagData != null) {
if (!input.readFully(tagData.data, 0, currentTagHeader.dataSize, true)) {
return RESULT_END_OF_INPUT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
/**
* Parses Script Data tags from an FLV stream and extracts metadata information.
*/
final class ScriptTagPayloadReader extends TagPayloadReader {
/* package */ final class ScriptTagPayloadReader extends TagPayloadReader {

// AMF object types
private static final int AMF_TYPE_UNKNOWN = -1;
Expand All @@ -50,19 +50,20 @@ public ScriptTagPayloadReader(TrackOutput output) {

@Override
public void seek() {

// Do nothing.
}

@Override
protected boolean parseHeader(ParsableByteArray data) throws UnsupportedTrack {
protected boolean parseHeader(ParsableByteArray data) throws UnsupportedFormatException {
return true;
}

@SuppressWarnings("unchecked")
@Override
protected void parsePayload(ParsableByteArray data, long timeUs) {
// Read message name (don't storing it as we are not going to give it any use)
// Read message name (don't store it because we don't yet have a use for it).
readAMFData(data, AMF_TYPE_UNKNOWN);
// Read message data.
Object obj = readAMFData(data, AMF_TYPE_UNKNOWN);

if (obj instanceof Map) {
Expand All @@ -74,7 +75,7 @@ protected void parsePayload(ParsableByteArray data, long timeUs) {

switch (entry.getKey()) {
case "duration":
this.durationUs = (long)(C.MICROS_PER_SECOND * (Double)(entry.getValue()));
setDurationUs((long) (C.MICROS_PER_SECOND * (Double)(entry.getValue())));
break;

default:
Expand Down Expand Up @@ -198,4 +199,5 @@ private Date readAMFDate(ParsableByteArray data) {
data.readUnsignedShort();
return date;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,20 @@
*/
/* package */ abstract class TagPayloadReader {

/**
* Thrown when the format is not supported.
*/
public static final class UnsupportedFormatException extends Exception {

public UnsupportedFormatException(String msg) {
super(msg);
}

}

protected final TrackOutput output;

// Duration of the track
protected long durationUs;
private long durationUs;

/**
* @param output A {@link TrackOutput} to which samples should be written.
Expand All @@ -38,61 +48,60 @@ protected TagPayloadReader(TrackOutput output) {
}

/**
* Notifies the reader that a seek has occurred.
* <p>
* Following a call to this method, the data passed to the next invocation of
* {@link #consume(ParsableByteArray, long)} will not be a continuation of the data that
* was previously passed. Hence the reader should reset any internal state.
* Sets duration in microseconds.
*
* @param durationUs duration in microseconds.
*/
public abstract void seek();
public final void setDurationUs(long durationUs) {
this.durationUs = durationUs;
}

/**
* Parses tag header
* @param data Buffer where the tag header is stored
* @return True if header was parsed successfully and then payload should be read;
* Otherwise, false
* @throws UnsupportedTrack
* Gets the duration in microseconds.
*
* @return The duration in microseconds.
*/
protected abstract boolean parseHeader(ParsableByteArray data) throws UnsupportedTrack;
public final long getDurationUs() {
return durationUs;
}

/**
* Parses tag payload
* @param data Buffer where tag payload is stored
* @param timeUs Time position of the frame
* Notifies the reader that a seek has occurred.
* <p>
* Following a call to this method, the data passed to the next invocation of
* {@link #consume(ParsableByteArray, long)} will not be a continuation of the data that
* was previously passed. Hence the reader should reset any internal state.
*/
protected abstract void parsePayload(ParsableByteArray data, long timeUs);
public abstract void seek();

/**
* Consumes payload data.
*
* @param data The payload data to consume.
* @param timeUs The timestamp associated with the payload.
*/
public void consume(ParsableByteArray data, long timeUs) throws UnsupportedTrack {
public final void consume(ParsableByteArray data, long timeUs) throws UnsupportedFormatException {
if (parseHeader(data)) {
parsePayload(data, timeUs);
}
}

/**
* Sets duration in microseconds
* @param durationUs duration in microseconds
* Parses tag header.
*
* @param data Buffer where the tag header is stored.
* @return True if the header was parsed successfully and the payload should be read. False
* otherwise.
* @throws UnsupportedFormatException
*/
public void setDurationUs(long durationUs) {
this.durationUs = durationUs;
}
protected abstract boolean parseHeader(ParsableByteArray data) throws UnsupportedFormatException;

public long getDurationUs() {
return durationUs;
}
/**
* Thrown when format described in the AudioTrack is not supported
* Parses tag payload.
*
* @param data Buffer where tag payload is stored
* @param timeUs Time position of the frame
*/
public static final class UnsupportedTrack extends Exception {

public UnsupportedTrack(String msg) {
super(msg);
}
protected abstract void parsePayload(ParsableByteArray data, long timeUs);

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
/**
* Parses video tags from an FLV stream and extracts H.264 nal units.
*/
final class VideoTagPayloadReader extends TagPayloadReader {
/* package */ final class VideoTagPayloadReader extends TagPayloadReader {
private static final String TAG = "VideoTagPayloadReader";

// Video codec
Expand Down Expand Up @@ -63,25 +63,23 @@ final class VideoTagPayloadReader extends TagPayloadReader {
*/
public VideoTagPayloadReader(TrackOutput output) {
super(output);

nalStartCode = new ParsableByteArray(NalUnitUtil.NAL_START_CODE);
nalLength = new ParsableByteArray(4);
}

@Override
public void seek() {

// Do nothing.
}

@Override
protected boolean parseHeader(ParsableByteArray data) throws UnsupportedTrack {
protected boolean parseHeader(ParsableByteArray data) throws UnsupportedFormatException {
int header = data.readUnsignedByte();
int frameType = (header >> 4) & 0x0F;
int videoCodec = (header & 0x0F);

// Support just H.264 encoded content.
if (videoCodec != VIDEO_CODEC_AVC) {
throw new UnsupportedTrack("Video codec not supported. Codec: " + videoCodec);
throw new UnsupportedFormatException("Video format not supported: " + videoCodec);
}
this.frameType = frameType;
return (frameType != VIDEO_FRAME_VIDEO_INFO);
Expand Down Expand Up @@ -113,7 +111,7 @@ protected void parsePayload(ParsableByteArray data, long timeUs) {

// Construct and output the format.
MediaFormat mediaFormat = MediaFormat.createVideoFormat(MediaFormat.NO_VALUE,
MimeTypes.VIDEO_H264, MediaFormat.NO_VALUE, MediaFormat.NO_VALUE, durationUs,
MimeTypes.VIDEO_H264, MediaFormat.NO_VALUE, MediaFormat.NO_VALUE, getDurationUs(),
avcData.width, avcData.height, avcData.initializationData, MediaFormat.NO_VALUE,
avcData.pixelWidthAspectRatio);
output.format(mediaFormat);
Expand Down

0 comments on commit 950cc70

Please sign in to comment.