AMPEG4AudioAssembler.cpp revision 39ddf8e0f18766f7ba1e3246b774aa6ebd93eea8
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "AMPEG4AudioAssembler.h"
18
19#include "ARTPSource.h"
20
21#include <media/stagefright/foundation/ABuffer.h>
22#include <media/stagefright/foundation/ADebug.h>
23#include <media/stagefright/foundation/AMessage.h>
24
25namespace android {
26
27AMPEG4AudioAssembler::AMPEG4AudioAssembler(const sp<AMessage> &notify)
28    : mNotifyMsg(notify),
29      mAccessUnitRTPTime(0),
30      mNextExpectedSeqNoValid(false),
31      mNextExpectedSeqNo(0),
32      mAccessUnitDamaged(false) {
33}
34
35AMPEG4AudioAssembler::~AMPEG4AudioAssembler() {
36}
37
38ARTPAssembler::AssemblyStatus AMPEG4AudioAssembler::assembleMore(
39        const sp<ARTPSource> &source) {
40    AssemblyStatus status = addPacket(source);
41    if (status == MALFORMED_PACKET) {
42        mAccessUnitDamaged = true;
43    }
44    return status;
45}
46
47ARTPAssembler::AssemblyStatus AMPEG4AudioAssembler::addPacket(
48        const sp<ARTPSource> &source) {
49    List<sp<ABuffer> > *queue = source->queue();
50
51    if (queue->empty()) {
52        return NOT_ENOUGH_DATA;
53    }
54
55    if (mNextExpectedSeqNoValid) {
56        List<sp<ABuffer> >::iterator it = queue->begin();
57        while (it != queue->end()) {
58            if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) {
59                break;
60            }
61
62            it = queue->erase(it);
63        }
64
65        if (queue->empty()) {
66            return NOT_ENOUGH_DATA;
67        }
68    }
69
70    sp<ABuffer> buffer = *queue->begin();
71
72    if (!mNextExpectedSeqNoValid) {
73        mNextExpectedSeqNoValid = true;
74        mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
75    } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
76#if VERBOSE
77        LOG(VERBOSE) << "Not the sequence number I expected";
78#endif
79
80        return WRONG_SEQUENCE_NUMBER;
81    }
82
83    uint32_t rtpTime;
84    CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
85
86    if (mPackets.size() > 0 && rtpTime != mAccessUnitRTPTime) {
87        submitAccessUnit();
88    }
89    mAccessUnitRTPTime = rtpTime;
90
91    mPackets.push_back(buffer);
92
93    queue->erase(queue->begin());
94    ++mNextExpectedSeqNo;
95
96    return OK;
97}
98
99void AMPEG4AudioAssembler::submitAccessUnit() {
100    CHECK(!mPackets.empty());
101
102#if VERBOSE
103    LOG(VERBOSE) << "Access unit complete (" << mPackets.size() << " packets)";
104#endif
105
106    uint64_t ntpTime;
107    CHECK((*mPackets.begin())->meta()->findInt64(
108                "ntp-time", (int64_t *)&ntpTime));
109
110    size_t totalSize = 0;
111    List<sp<ABuffer> >::iterator it = mPackets.begin();
112    while (it != mPackets.end()) {
113        const sp<ABuffer> &unit = *it;
114
115        size_t n = 0;
116        while (unit->data()[n] == 0xff) {
117            ++n;
118        }
119        ++n;
120
121        totalSize += unit->size() - n;
122        ++it;
123    }
124
125    sp<ABuffer> accessUnit = new ABuffer(totalSize);
126    size_t offset = 0;
127    it = mPackets.begin();
128    while (it != mPackets.end()) {
129        const sp<ABuffer> &unit = *it;
130
131        size_t n = 0;
132        while (unit->data()[n] == 0xff) {
133            ++n;
134        }
135        ++n;
136
137        memcpy((uint8_t *)accessUnit->data() + offset,
138               unit->data() + n, unit->size() - n);
139
140        offset += unit->size() - n;
141
142        ++it;
143    }
144
145    accessUnit->meta()->setInt64("ntp-time", ntpTime);
146
147#if 0
148    printf(mAccessUnitDamaged ? "X" : ".");
149    fflush(stdout);
150#endif
151
152    if (mAccessUnitDamaged) {
153        accessUnit->meta()->setInt32("damaged", true);
154    }
155
156    mPackets.clear();
157    mAccessUnitDamaged = false;
158
159    sp<AMessage> msg = mNotifyMsg->dup();
160    msg->setObject("access-unit", accessUnit);
161    msg->post();
162}
163
164void AMPEG4AudioAssembler::packetLost() {
165    CHECK(mNextExpectedSeqNoValid);
166    ++mNextExpectedSeqNo;
167
168    mAccessUnitDamaged = true;
169}
170
171void AMPEG4AudioAssembler::onByeReceived() {
172    sp<AMessage> msg = mNotifyMsg->dup();
173    msg->setInt32("eos", true);
174    msg->post();
175}
176
177}  // namespace android
178