Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d630f593 authored by John Grossman's avatar John Grossman
Browse files

LibAAH_RTP: Add support for AAC in MP4.



Cherry picked from Ie8298eb9d253fc6ede448da87660a60d23170987 and
conflicts fixed by hand.

Change-Id: I6f0a59357ba1a3d57caf67d2eb0ade7486723e7b
Signed-off-by: default avatarJohn Grossman <johngro@google.com>
parent 3f4b1c4d
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -159,8 +159,8 @@ void AAH_DecoderPump::queueToRenderer(MediaBuffer* decoded_sample) {

                res = renderer_->queueTimedBuffer(pcm_payload, ts);
                if (res != OK) {
                    ALOGE("Failed to queue %d byte audio track buffer with media"
                          " PTS %lld. (res = %d)", decoded_amt, ts, res);
                    ALOGE("Failed to queue %d byte audio track buffer with"
                          " media PTS %lld. (res = %d)", decoded_amt, ts, res);
                } else {
                    last_queued_pts_valid_ = true;
                    last_queued_pts_ = ts;
@@ -291,8 +291,8 @@ void* AAH_DecoderPump::workThread() {
    // thread_status_.
    thread_status_ = decoder_->start(format_.get());
    if (OK != thread_status_) {
        ALOGE("AAH_DecoderPump's work thread failed to start decoder (res = %d)",
                thread_status_);
        ALOGE("AAH_DecoderPump's work thread failed to start decoder"
              " (res = %d)", thread_status_);
        return NULL;
    }

+8 −3
Original line number Diff line number Diff line
@@ -217,14 +217,15 @@ class AAH_RXPlayer : public MediaPlayerInterface {
        status_t getStatus() const { return status_; }

      protected:
        virtual ~Substream() {
            shutdown();
        }
        virtual ~Substream();

      private:
        void                cleanupDecoder();
        bool                shouldAbort(const char* log_tag);
        void                processCompletedBuffer();
        bool                setupSubstreamMeta();
        bool                setupMP3SubstreamMeta();
        bool                setupAACSubstreamMeta();
        bool                setupSubstreamType(uint8_t substream_type,
                                               uint8_t codec_type);

@@ -235,12 +236,16 @@ class AAH_RXPlayer : public MediaPlayerInterface {
        bool                substream_details_known_;
        uint8_t             substream_type_;
        uint8_t             codec_type_;
        const char*         codec_mime_type_;
        sp<MetaData>        substream_meta_;

        MediaBuffer*        buffer_in_progress_;
        uint32_t            expected_buffer_size_;
        uint32_t            buffer_filled_;

        Vector<uint8_t>     aux_data_in_progress_;
        uint32_t            aux_data_expected_size_;

        sp<AAH_DecoderPump> decoder_;

        static int64_t      kAboutToUnderflowThreshold;
+6 −4
Original line number Diff line number Diff line
@@ -431,8 +431,8 @@ bool AAH_RXPlayer::processRX(PacketBuffer* pb) {
        // Looks like a NAK packet; make sure its long enough.

        if (amt < static_cast<ssize_t>(sizeof(RetransRequest))) {
            ALOGV("Dropping packet, too short to contain NAK payload (%u bytes)",
                  static_cast<uint32_t>(amt));
            ALOGV("Dropping packet, too short to contain NAK payload"
                  " (%u bytes)", static_cast<uint32_t>(amt));
            goto drop_packet;
        }

@@ -441,7 +441,8 @@ bool AAH_RXPlayer::processRX(PacketBuffer* pb) {
        gap.start_seq_ = ntohs(rtr->start_seq_);
        gap.end_seq_   = ntohs(rtr->end_seq_);

        ALOGV("Process NAK for gap at [%hu, %hu]", gap.start_seq_, gap.end_seq_);
        ALOGV("Process NAK for gap at [%hu, %hu]",
                gap.start_seq_, gap.end_seq_);
        ring_buffer_.processNAK(&gap);

        return true;
@@ -770,7 +771,8 @@ bool AAH_RXPlayer::processGaps() {
            ALOGE("Error when sending retransmit request (%d)", errno);
        } else {
            ALOGV("%s request for range [%hu, %hu] sent",
                  (kGS_FastStartGap == gap_status) ? "Fast Start" : "Retransmit",
                  (kGS_FastStartGap == gap_status) ? "Fast Start"
                                                   : "Retransmit",
                  gap.start_seq_, gap.end_seq_);
        }

+2 −2
Original line number Diff line number Diff line
@@ -116,8 +116,8 @@ bool AAH_RXPlayer::RXRingBuffer::pushBuffer(PacketBuffer* buf,

    // Check for overflow first.
    if ((!(norm_seq & 0x8000)) && (norm_seq >= (capacity_ - 1))) {
        ALOGW("Ring buffer overflow; cap = %u, [rd, wr] = [%hu, %hu], seq = %hu",
              capacity_, rd_seq_, norm_wr_seq + rd_seq_, seq);
        ALOGW("Ring buffer overflow; cap = %u, [rd, wr] = [%hu, %hu],"
              " seq = %hu", capacity_, rd_seq_, norm_wr_seq + rd_seq_, seq);
        PacketBuffer::destroy(buf);
        return false;
    }
+280 −101
Original line number Diff line number Diff line
@@ -27,6 +27,11 @@
#include <media/stagefright/Utils.h>

#include "aah_rx_player.h"
#include "aah_tx_packet.h"

inline uint32_t min(uint32_t a, uint32_t b) {
    return (a < b ? a : b);
}

namespace android {

@@ -38,6 +43,7 @@ AAH_RXPlayer::Substream::Substream(uint32_t ssrc, OMXClient& omx) {
    substream_details_known_ = false;
    buffer_in_progress_ = NULL;
    status_ = OK;
    codec_mime_type_ = "";

    decoder_ = new AAH_DecoderPump(omx);
    if (decoder_ == NULL) {
@@ -52,6 +58,9 @@ AAH_RXPlayer::Substream::Substream(uint32_t ssrc, OMXClient& omx) {
    cleanupBufferInProgress();
}

AAH_RXPlayer::Substream::~Substream() {
    shutdown();
}

void AAH_RXPlayer::Substream::shutdown() {
    substream_meta_ = NULL;
@@ -69,6 +78,9 @@ void AAH_RXPlayer::Substream::cleanupBufferInProgress() {
    expected_buffer_size_ = 0;
    buffer_filled_ = 0;
    waiting_for_rap_ = true;

    aux_data_in_progress_.clear();
    aux_data_expected_size_ = 0;
}

void AAH_RXPlayer::Substream::cleanupDecoder() {
@@ -129,16 +141,16 @@ void AAH_RXPlayer::Substream::processPayloadStart(uint8_t* buf,
    // one that does not conflict with any previously received substream type.
    uint8_t header_type = (buf[1] >> 4) & 0xF;
    switch (header_type) {
        case 0x01:
        case TRTPPacket::kHeaderTypeAudio:
            // Audio, yay!  Just break.  We understand audio payloads.
            break;
        case 0x02:
        case TRTPPacket::kHeaderTypeVideo:
            ALOGV("RXed packet with unhandled TRTP header type (Video).");
            return;
        case 0x03:
        case TRTPPacket::kHeaderTypeSubpicture:
            ALOGV("RXed packet with unhandled TRTP header type (Subpicture).");
            return;
        case 0x04:
        case TRTPPacket::kHeaderTypeControl:
            ALOGV("RXed packet with unhandled TRTP header type (Control).");
            return;
        default:
@@ -148,15 +160,15 @@ void AAH_RXPlayer::Substream::processPayloadStart(uint8_t* buf,
    }

    if (substream_details_known_ && (header_type != substream_type_)) {
        ALOGV("RXed TRTP Payload for SSRC=0x%08x where header type (%u) does not"
              " match previously received header type (%u)",
        ALOGV("RXed TRTP Payload for SSRC=0x%08x where header type (%u) does"
              " not match previously received header type (%u)",
              ssrc_, header_type, substream_type_);
        return;
    }

    // Check the flags to see if there is another 32 bits of timestamp present.
    uint32_t trtp_header_len = 6;
    bool ts_valid = buf[1] & 0x1;
    bool ts_valid = buf[1] & TRTPPacket::kFlag_TSValid;
    if (ts_valid) {
        min_length += 4;
        trtp_header_len += 4;
@@ -168,11 +180,7 @@ void AAH_RXPlayer::Substream::processPayloadStart(uint8_t* buf,
    }

    // Extract the TRTP length field and sanity check it.
    uint32_t trtp_len;
    trtp_len = (static_cast<uint32_t>(buf[2]) << 24) |
        (static_cast<uint32_t>(buf[3]) << 16) |
        (static_cast<uint32_t>(buf[4]) <<  8) |
        static_cast<uint32_t>(buf[5]);
    uint32_t trtp_len = U32_AT(buf + 2);
    if (trtp_len < min_length) {
        ALOGV("TRTP length (%u) is too short to be valid.  Must be at least %u"
              " bytes.", trtp_len, min_length);
@@ -183,17 +191,14 @@ void AAH_RXPlayer::Substream::processPayloadStart(uint8_t* buf,
    int64_t ts = 0;
    uint32_t parse_offset = 6;
    if (ts_valid) {
        ts = (static_cast<int64_t>(buf[parse_offset    ]) << 56) |
            (static_cast<int64_t>(buf[parse_offset + 1]) << 48) |
            (static_cast<int64_t>(buf[parse_offset + 2]) << 40) |
            (static_cast<int64_t>(buf[parse_offset + 3]) << 32);
        ts |= ts_lower;
        uint32_t ts_upper = U32_AT(buf + parse_offset);
        parse_offset += 4;
        ts = (static_cast<int64_t>(ts_upper) << 32) | ts_lower;
    }

    // Check the flags to see if there is another 24 bytes of timestamp
    // transformation present.
    if (buf[1] & 0x2) {
    if (buf[1] & TRTPPacket::kFlag_TSTransformPresent) {
        min_length += 24;
        parse_offset += 24;
        trtp_header_len += 24;
@@ -219,8 +224,8 @@ void AAH_RXPlayer::Substream::processPayloadStart(uint8_t* buf,

    if (amt < min_length) {
        ALOGV("TRTP porttion of RTP payload (%u bytes) too small to contain"
              " entire TRTP header.  TRTP does not currently support fragmenting"
              " TRTP headers across RTP payloads", amt);
              " entire TRTP header.  TRTP does not currently support"
              " fragmenting TRTP headers across RTP payloads", amt);
        return;
    }

@@ -238,16 +243,42 @@ void AAH_RXPlayer::Substream::processPayloadStart(uint8_t* buf,
        decoder_->setRenderVolume(volume);
    }

    // TODO : move all of the constant flag and offset definitions for TRTP up
    // into some sort of common header file.
    if (waiting_for_rap_ && !(flags & 0x08)) {
    if (waiting_for_rap_ && !(flags & TRTPAudioPacket::kFlag_RandomAccessPoint)) {
        ALOGV("Dropping non-RAP TRTP Audio Payload while waiting for RAP.");
        return;
    }

    if (flags & 0x10) {
        ALOGV("Dropping TRTP Audio Payload with aux codec data present (only"
              " handle MP3 right now, and it has no aux data)");
    // Check for the presence of codec aux data.
    if (flags & TRTPAudioPacket::kFlag_AuxLengthPresent) {
        min_length += 4;
        trtp_header_len += 4;

        if (trtp_len < min_length) {
            ALOGV("TRTP length (%u) is too short to be a valid audio payload.  "
                  "Must be at least %u bytes.", trtp_len, min_length);
            return;
        }

        if (amt < min_length) {
            ALOGV("TRTP porttion of RTP payload (%u bytes) too small to contain"
                  " entire TRTP header.  TRTP does not currently support"
                  " fragmenting TRTP headers across RTP payloads", amt);
            return;
        }

        aux_data_expected_size_ = U32_AT(buf + parse_offset);
        aux_data_in_progress_.clear();
        if (aux_data_in_progress_.capacity() < aux_data_expected_size_) {
            aux_data_in_progress_.setCapacity(aux_data_expected_size_);
        }
    } else {
        aux_data_expected_size_ = 0;
    }

    if ((aux_data_expected_size_ + trtp_header_len) > trtp_len) {
        ALOGV("Expected codec aux data length (%u) and TRTP header overhead"
              " (%u) too large for total TRTP payload length (%u).",
             aux_data_expected_size_, trtp_header_len, trtp_len);
        return;
    }

@@ -255,7 +286,9 @@ void AAH_RXPlayer::Substream::processPayloadStart(uint8_t* buf,
    // the buffer in progress and pack as much payload as we can into it.  If
    // the payload is finished once we are done, go ahead and send the payload
    // to the decoder.
    expected_buffer_size_ = trtp_len - trtp_header_len;
    expected_buffer_size_ = trtp_len
                          - trtp_header_len
                          - aux_data_expected_size_;
    if (!expected_buffer_size_) {
        ALOGV("Dropping TRTP Audio Payload with 0 Access Unit length");
        return;
@@ -263,9 +296,10 @@ void AAH_RXPlayer::Substream::processPayloadStart(uint8_t* buf,

    CHECK(amt >= trtp_header_len);
    uint32_t todo = amt - trtp_header_len;
    if (expected_buffer_size_ < todo) {
    if ((expected_buffer_size_ + aux_data_expected_size_) < todo) {
        ALOGV("Extra data (%u > %u) present in initial TRTP Audio Payload;"
              " dropping payload.", todo, expected_buffer_size_);
              " dropping payload.", todo,
              expected_buffer_size_ + aux_data_expected_size_);
        return;
    }

@@ -287,18 +321,32 @@ void AAH_RXPlayer::Substream::processPayloadStart(uint8_t* buf,
        return;
    }

    // TODO : set this based on the codec type indicated in the TRTP stream.
    // Right now, we only support MP3, so the choice is obvious.
    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
    meta->setCString(kKeyMIMEType, codec_mime_type_);
    if (ts_valid) {
        meta->setInt64(kKeyTime, ts);
    }

    if (amt > 0) {
    // Skip over the header we have already extracted.
    amt -= trtp_header_len;
    buf += trtp_header_len;

    // Extract as much of the expected aux data as we can.
    todo = min(aux_data_expected_size_, amt);
    if (todo) {
        aux_data_in_progress_.appendArray(buf, todo);
        buf += todo;
        amt -= todo;
    }

    // Extract as much of the expected payload as we can.
    todo = min(expected_buffer_size_, amt);
    if (todo > 0) {
        uint8_t* tgt =
            reinterpret_cast<uint8_t*>(buffer_in_progress_->data());
        memcpy(tgt + buffer_filled_, buf + trtp_header_len, todo);
        buffer_filled_ += amt;
        memcpy(tgt, buf, todo);
        buffer_filled_ = amt;
        buf += todo;
        amt -= todo;
    }

    if (buffer_filled_ >= expected_buffer_size_) {
@@ -318,6 +366,18 @@ void AAH_RXPlayer::Substream::processPayloadCont(uint8_t* buf,
        return;
    }

    CHECK(aux_data_in_progress_.size() <= aux_data_expected_size_);
    uint32_t aux_left = aux_data_expected_size_ - aux_data_in_progress_.size();
    if (aux_left) {
        uint32_t todo = min(aux_left, amt);
        aux_data_in_progress_.appendArray(buf, todo);
        amt -= todo;
        buf += todo;

        if (!amt)
            return;
    }

    CHECK(buffer_filled_ < expected_buffer_size_);
    uint32_t buffer_left = expected_buffer_size_ - buffer_filled_;
    if (amt > buffer_left) {
@@ -340,10 +400,6 @@ void AAH_RXPlayer::Substream::processPayloadCont(uint8_t* buf,
}

void AAH_RXPlayer::Substream::processCompletedBuffer() {
    const uint8_t* buffer_data = NULL;
    int sample_rate;
    int channel_count;
    size_t frame_size;
    status_t res;

    CHECK(NULL != buffer_in_progress_);
@@ -353,10 +409,91 @@ void AAH_RXPlayer::Substream::processCompletedBuffer() {
        goto bailout;
    }

    // Make sure our metadata used to initialize the decoder has been properly
    // set up.
    if (!setupSubstreamMeta())
        goto bailout;

    // If our decoder has not be set up, do so now.
    res = decoder_->init(substream_meta_);
    if (OK != res) {
        ALOGE("Failed to init decoder (res = %d)", res);
        cleanupDecoder();
        substream_meta_ = NULL;
        goto bailout;
    }

    // Queue the payload for decode.
    res = decoder_->queueForDecode(buffer_in_progress_);

    if (res != OK) {
        ALOGD("Failed to queue payload for decode, resetting decoder pump!"
             " (res = %d)", res);
        status_ = res;
        cleanupDecoder();
        cleanupBufferInProgress();
    }

    // NULL out buffer_in_progress before calling the cleanup helper.
    //
    // MediaBuffers use something of a hybrid ref-counting pattern which prevent
    // the AAH_DecoderPump's input queue from adding their own reference to the
    // MediaBuffer.  MediaBuffers start life with a reference count of 0, as
    // well as an observer which starts as NULL.  Before being given an
    // observer, the ref count cannot be allowed to become non-zero as it will
    // cause calls to release() to assert.  Basically, before a MediaBuffer has
    // an observer, they behave like non-ref counted obects where release()
    // serves the roll of delete.  After a MediaBuffer has an observer, they
    // become more like ref counted objects where add ref and release can be
    // used, and when the ref count hits zero, the MediaBuffer is handed off to
    // the observer.
    //
    // Given all of this, when we give the buffer to the decoder pump to wait in
    // the to-be-processed queue, the decoder cannot add a ref to the buffer as
    // it would in a traditional ref counting system.  Instead it needs to
    // "steal" the non-existent ref.  In the case of queue failure, we need to
    // make certain to release this non-existent reference so that the buffer is
    // cleaned up during the cleanupBufferInProgress helper.  In the case of a
    // successful queue operation, we need to make certain that the
    // cleanupBufferInProgress helper does not release the buffer since it needs
    // to remain alive in the queue.  We acomplish this by NULLing out the
    // buffer pointer before calling the cleanup helper.
    buffer_in_progress_ = NULL;

bailout:
    cleanupBufferInProgress();
}

bool AAH_RXPlayer::Substream::setupSubstreamMeta() {
    switch (codec_type_) {
        case TRTPAudioPacket::kCodecMPEG1Audio:
            codec_mime_type_ = MEDIA_MIMETYPE_AUDIO_MPEG;
            return setupMP3SubstreamMeta();

        case TRTPAudioPacket::kCodecAACAudio:
            codec_mime_type_ = MEDIA_MIMETYPE_AUDIO_AAC;
            return setupAACSubstreamMeta();

        default:
            ALOGV("Failed to setup substream metadata for unsupported codec"
                  " type (%u)", codec_type_);
            break;
    }

    return false;
}

bool AAH_RXPlayer::Substream::setupMP3SubstreamMeta() {
    const uint8_t* buffer_data = NULL;
    int sample_rate;
    int channel_count;
    size_t frame_size;
    status_t res;

    buffer_data = reinterpret_cast<const uint8_t*>(buffer_in_progress_->data());
    if (buffer_in_progress_->size() < 4) {
        ALOGV("MP3 payload too short to contain header, dropping payload.");
        goto bailout;
        return false;
    }

    // Extract the channel count and the sample rate from the MP3 header.  The
@@ -369,7 +506,7 @@ void AAH_RXPlayer::Substream::processCompletedBuffer() {
                               NULL,
                               NULL)) {
        ALOGV("Failed to parse MP3 header in payload, droping payload.");
        goto bailout;
        return false;
    }


@@ -381,8 +518,8 @@ void AAH_RXPlayer::Substream::processCompletedBuffer() {
        substream_meta_ = new MetaData();

        if (substream_meta_ == NULL) {
            ALOGE("Failed to allocate MetaData structure for substream");
            goto bailout;
            ALOGE("Failed to allocate MetaData structure for MP3 substream");
            return false;
        }

        substream_meta_->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
@@ -396,7 +533,7 @@ void AAH_RXPlayer::Substream::processCompletedBuffer() {

        if ((prev_channel_count != channel_count) ||
            (prev_sample_rate   != sample_rate)) {
            ALOGW("Format change detected, forcing decoder reset.");
            ALOGW("MP3 format change detected, forcing decoder reset.");
            cleanupDecoder();

            substream_meta_->setInt32(kKeyChannelCount, channel_count);
@@ -404,56 +541,90 @@ void AAH_RXPlayer::Substream::processCompletedBuffer() {
        }
    }

    // If our decoder has not be set up, do so now.
    res = decoder_->init(substream_meta_);
    if (OK != res) {
        ALOGE("Failed to init decoder (res = %d)", res);
    return true;
}

bool AAH_RXPlayer::Substream::setupAACSubstreamMeta() {
    int32_t sample_rate, channel_cnt;
    static const size_t overhead = sizeof(sample_rate)
                                 + sizeof(channel_cnt);

    if (aux_data_in_progress_.size() < overhead) {
        ALOGE("Not enough aux data (%u) to initialize AAC substream decoder",
                aux_data_in_progress_.size());
        return false;
    }

    const uint8_t* aux_data = aux_data_in_progress_.array();
    size_t aux_data_size = aux_data_in_progress_.size();
    sample_rate = U32_AT(aux_data);
    channel_cnt = U32_AT(aux_data + sizeof(sample_rate));

    const uint8_t* esds_data = NULL;
    size_t esds_data_size = 0;
    if (aux_data_size > overhead) {
        esds_data = aux_data + overhead;
        esds_data_size = aux_data_size - overhead;
    }

    // Do we already have metadata?  If so, has it changed at all?  If not, then
    // there should be nothing else to do.  Otherwise, release our old stream
    // metadata and make new metadata.
    if (substream_meta_ != NULL) {
        uint32_t type;
        const void* data;
        size_t size;
        int32_t prev_sample_rate;
        int32_t prev_channel_count;
        bool res;

        res = substream_meta_->findInt32(kKeySampleRate,   &prev_sample_rate);
        CHECK(res);
        res = substream_meta_->findInt32(kKeyChannelCount, &prev_channel_count);
        CHECK(res);

        // If nothing has changed about the codec aux data (esds, sample rate,
        // channel count), then we can just do nothing and get out.  Otherwise,
        // we will need to reset the decoder and make a new metadata object to
        // deal with the format change.
        bool hasData = (esds_data != NULL);
        bool hadData = substream_meta_->findData(kKeyESDS, &type, &data, &size);
        bool esds_change = (hadData != hasData);

        if (!esds_change && hasData)
            esds_change = ((size != esds_data_size) ||
                           memcmp(data, esds_data, size));

        if (!esds_change &&
            (prev_sample_rate   == sample_rate) &&
            (prev_channel_count == channel_cnt)) {
            return true;  // no change, just get out.
        }

        ALOGW("AAC format change detected, forcing decoder reset.");
        cleanupDecoder();
        substream_meta_ = NULL;
        goto bailout;
    }

    // Queue the payload for decode.
    res = decoder_->queueForDecode(buffer_in_progress_);
    CHECK(substream_meta_ == NULL);

    if (res != OK) {
        ALOGD("Failed to queue payload for decode, resetting decoder pump!"
              " (res = %d)", res);
        status_ = res;
        cleanupDecoder();
        cleanupBufferInProgress();
    substream_meta_ = new MetaData();
    if (substream_meta_ == NULL) {
        ALOGE("Failed to allocate MetaData structure for AAC substream");
        return false;
    }

    // NULL out buffer_in_progress before calling the cleanup helper.
    //
    // MediaBuffers use something of a hybrid ref-counting pattern which prevent
    // the AAH_DecoderPump's input queue from adding their own reference to the
    // MediaBuffer.  MediaBuffers start life with a reference count of 0, as
    // well as an observer which starts as NULL.  Before being given an
    // observer, the ref count cannot be allowed to become non-zero as it will
    // cause calls to release() to assert.  Basically, before a MediaBuffer has
    // an observer, they behave like non-ref counted obects where release()
    // serves the roll of delete.  After a MediaBuffer has an observer, they
    // become more like ref counted objects where add ref and release can be
    // used, and when the ref count hits zero, the MediaBuffer is handed off to
    // the observer.
    //
    // Given all of this, when we give the buffer to the decoder pump to wait in
    // the to-be-processed queue, the decoder cannot add a ref to the buffer as
    // it would in a traditional ref counting system.  Instead it needs to
    // "steal" the non-existent ref.  In the case of queue failure, we need to
    // make certain to release this non-existent reference so that the buffer is
    // cleaned up during the cleanupBufferInProgress helper.  In the case of a
    // successful queue operation, we need to make certain that the
    // cleanupBufferInProgress helper does not release the buffer since it needs
    // to remain alive in the queue.  We acomplish this by NULLing out the
    // buffer pointer before calling the cleanup helper.
    buffer_in_progress_ = NULL;
    substream_meta_->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
    substream_meta_->setInt32  (kKeySampleRate,   sample_rate);
    substream_meta_->setInt32  (kKeyChannelCount, channel_cnt);

bailout:
    cleanupBufferInProgress();
    if (esds_data) {
        substream_meta_->setData(kKeyESDS, kTypeESDS,
                                 esds_data, esds_data_size);
    }

    return true;
}

void AAH_RXPlayer::Substream::processTSTransform(const LinearTransform& trans) {
    if (decoder_ != NULL) {
@@ -471,26 +642,34 @@ bool AAH_RXPlayer::Substream::isAboutToUnderflow() {

bool AAH_RXPlayer::Substream::setupSubstreamType(uint8_t substream_type,
                                                 uint8_t codec_type) {
    // Sanity check the codec type.  Right now we only support MP3.  Also check
    // for conflicts with previously delivered codec types.
    if (substream_details_known_ && (codec_type != codec_type_)) {
        ALOGV("RXed TRTP Payload for SSRC=0x%08x where codec type (%u) does not"
              " match previously received codec type (%u)",
    // Sanity check the codec type.  Right now we only support MP3 and AAC.
    // Also check for conflicts with previously delivered codec types.
    if (substream_details_known_) {
        if (codec_type != codec_type_) {
            ALOGV("RXed TRTP Payload for SSRC=0x%08x where codec type (%u) does"
                  " not match previously received codec type (%u)",
                 ssrc_, codec_type, codec_type_);
            return false;
        }

    if (codec_type != 0x03) {
        ALOGV("RXed TRTP Audio Payload for SSRC=0x%08x with unsupported codec"
              " type (%u)", ssrc_, codec_type);
        return true;
    }

    switch (codec_type) {
        // MP3 and AAC are all we support right now.
        case TRTPAudioPacket::kCodecMPEG1Audio:
        case TRTPAudioPacket::kCodecAACAudio:
            break;

        default:
            ALOGV("RXed TRTP Audio Payload for SSRC=0x%08x with unsupported"
                  " codec type (%u)", ssrc_, codec_type);
            return false;
    }

    if (!substream_details_known_) {
    substream_type_ = substream_type;
    codec_type_ = codec_type;
    substream_details_known_ = true;
    }

    return true;
}
Loading