Skip to content

Commit

Permalink
Support for PCMA audio
Browse files Browse the repository at this point in the history
Added support for PCMA audio in addition to AAC.
Also, doesn't crash anymore if fmtp is not present for audio
configurations.
  • Loading branch information
noseglid committed Dec 30, 2014
1 parent 59b5320 commit 8f805a2
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 17 deletions.
3 changes: 2 additions & 1 deletion src/com/axis/ErrorManager.as
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ package com.axis {
'827': "Connection broken. The stream has been stopped.",
'828': "Unable to seek.",
'829': "httpm only supports Content-Type: 'multipart/x-mixed-replace'",
'830': "Unable to set buffer. This might not work for this stream-type, or this particular stream."
'830': "Unable to set buffer. This might not work for this stream-type, or this particular stream.",
'831': "Unsupported Audio or Video format: %p"
};

public static function dispatchError(errorCode:Number, errorData:Array = null, throwError:Boolean = false):void {
Expand Down
75 changes: 62 additions & 13 deletions src/com/axis/rtspclient/FLVMux.as
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ package com.axis.rtspclient {
}

if (sdp.getMediaBlock('audio')) {
createAudioSpecificConfigTag(ByteArrayUtils.createFromHexstring(sdp.getMediaBlock('audio').fmtp['config']));
createAudioSpecificConfigTag(sdp.getMediaBlock('audio'));
}

pushData();
Expand Down Expand Up @@ -197,7 +197,7 @@ package com.axis.rtspclient {
height : params.height,
avcprofile : params.profile,
avclevel : params.level,
metadatacreator : "Slush FLV Muxer",
metadatacreator : "Locomote FLV Muxer",
creationdate : new Date().toString()
});

Expand Down Expand Up @@ -271,7 +271,29 @@ package com.axis.rtspclient {
}
}

public function createAudioSpecificConfigTag(config:ByteArray):void {
private function getAudioParameters(name):Object {
Logger.log(this.ns.info.audioBufferLength);
switch (name.toLowerCase()) {
case 'mpeg4-generic':
return {
format: 0xA, /* AAC */
depth: 0x1, /* 16 bits per sample */
sampling: 0x3, /* 44 kHz */
type: 0x1 /* Stereo */
};
case 'pcma':
return {
format: 0x3, /* Linear PCM */
depth: 0x0, /* 8 bits per sample */
sampling: 0x5, /* 5,5 kHz, which is as close to 8 kHz we can get, this should probably be up-sampled */
type: 0x0 /* Mono */
};
default:
return false;
}
}

public function createAudioSpecificConfigTag(config:Object):void {
var start:uint = container.position;

/* FLV Tag */
Expand All @@ -282,12 +304,24 @@ package com.axis.rtspclient {
container.writeByte(0x00); // StreamID - always 0
container.writeByte(0x00); // StreamID - always 0

var audioParams:Object;
for (var pt:Object in config.rtpmap) {
audioParams = getAudioParameters(config.rtpmap[pt].name);
if (false !== audioParams) {
break;
}
/* Didn't get any params on first type, and multiple types are not supported. */
ErrorManager.dispatchError(831, [ config.rtpmap[pt].name ], true);
}

/* Audio Tag Header */
container.writeByte(0xA << 4 | 0x3 << 2 | 0x1 << 1 | 0x0 << 0); // Format << 4 | Sampling << 2 | Size << 1 | Type << 0
container.writeByte(0x0); // AAC Sequence Header
container.writeByte(audioParams.format << 4 | audioParams.sampling << 2 | audioParams.depth << 1 | audioParams.type << 0);

/* AudioSpecificConfig */
container.writeBytes(config);
if (0xA === audioParams.format) {
/* A little more setup required if this is AAC */
container.writeByte(0x0); // AAC Sequence Header
container.writeBytes(ByteArrayUtils.createFromHexstring(config.fmtp['config']));
}

var size:uint = container.position - start;

Expand Down Expand Up @@ -338,9 +372,9 @@ package com.axis.rtspclient {
container.writeUnsignedInt(size + 11);
}

public function createAudioTag(aacframe:AACFrame):void {
public function createAudioTag(name:String, frame:*):void {
var start:uint = container.position;
var ts:uint = aacframe.timestamp;
var ts:uint = frame.timestamp;
if (audioInitialTimestamp === -1) {
audioInitialTimestamp = ts;
}
Expand All @@ -355,12 +389,22 @@ package com.axis.rtspclient {
container.writeByte(0x00); // StreamID - always 0
container.writeByte(0x00); // StreamID - always 0

var audioParams:Object = getAudioParameters(name);
if (false === audioParams) {
/* No audio params for this name. */
ErrorManager.dispatchError(831, [ name ], true);
}

/* Audio Tag Header */
container.writeByte(0xA << 4 | 0x3 << 2 | 0x1 << 1 | 0x1 << 0); // Format << 4 | Sampling << 2 | Size << 1 | Type << 0
container.writeByte(0x1); // AAC Raw
container.writeByte(audioParams.format << 4 | audioParams.sampling << 2 | audioParams.depth << 1 | audioParams.type << 0);

if (0xA === audioParams.format) {
/* A little more setup required if this is AAC */
container.writeByte(0x1); // AAC Raw
}

/* Audio Data */
aacframe.writeStream(container);
frame.writeStream(container);

var size:uint = container.position - start;

Expand Down Expand Up @@ -406,7 +450,12 @@ package com.axis.rtspclient {
}

public function onAACFrame(aacframe:AACFrame):void {
createAudioTag(aacframe);
createAudioTag('mpeg4-generic', aacframe);
pushData();
}

public function onPCMAFrame(pcmaframe:PCMAFrame):void {
createAudioTag('pcma', pcmaframe);
pushData();
}

Expand Down
2 changes: 1 addition & 1 deletion src/com/axis/rtspclient/RTP.as
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ package com.axis.rtspclient {
Logger.log('Media description for payload type: ' + pt + ' not provided.');
}

super(media.type.toUpperCase() + '_PACKET', false, false);
super(media.type.toUpperCase() + '_' + media.rtpmap[pt].name.toUpperCase() + '_PACKET', false, false);

this.data = pkt;
}
Expand Down
7 changes: 5 additions & 2 deletions src/com/axis/rtspclient/RTSPClient.as
Original file line number Diff line number Diff line change
Expand Up @@ -336,11 +336,14 @@ package com.axis.rtspclient {
this.flvmux = new FLVMux(this.ns, this.sdp);
var analu:ANALU = new ANALU();
var aaac:AAAC = new AAAC(sdp);
var apcma:APCMA = new APCMA();

this.addEventListener("VIDEO_PACKET", analu.onRTPPacket);
this.addEventListener("AUDIO_PACKET", aaac.onRTPPacket);
this.addEventListener("VIDEO_H264_PACKET", analu.onRTPPacket);
this.addEventListener("AUDIO_MPEG4-GENERIC_PACKET", aaac.onRTPPacket);
this.addEventListener("AUDIO_PCMA_PACKET", apcma.onRTPPacket);
analu.addEventListener(NALU.NEW_NALU, flvmux.onNALU);
aaac.addEventListener(AACFrame.NEW_FRAME, flvmux.onAACFrame);
apcma.addEventListener(PCMAFrame.NEW_FRAME, flvmux.onPCMAFrame);
break;

case STATE_PLAYING:
Expand Down

0 comments on commit 8f805a2

Please sign in to comment.