AMPEG4AudioAssembler.cpp revision 8d342970108926c4ea355c90d26a2a353ec0fd47
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    size_t totalSize = 0;
107    List<sp<ABuffer> >::iterator it = mPackets.begin();
108    while (it != mPackets.end()) {
109        const sp<ABuffer> &unit = *it;
110
111        size_t n = 0;
112        while (unit->data()[n] == 0xff) {
113            ++n;
114        }
115        ++n;
116
117        totalSize += unit->size() - n;
118        ++it;
119    }
120
121    sp<ABuffer> accessUnit = new ABuffer(totalSize);
122    size_t offset = 0;
123    it = mPackets.begin();
124    while (it != mPackets.end()) {
125        const sp<ABuffer> &unit = *it;
126
127        size_t n = 0;
128        while (unit->data()[n] == 0xff) {
129            ++n;
130        }
131        ++n;
132
133        memcpy((uint8_t *)accessUnit->data() + offset,
134               unit->data() + n, unit->size() - n);
135
136        offset += unit->size() - n;
137
138        ++it;
139    }
140
141    CopyTimes(accessUnit, *mPackets.begin());
142
143#if 0
144    printf(mAccessUnitDamaged ? "X" : ".");
145    fflush(stdout);
146#endif
147
148    if (mAccessUnitDamaged) {
149        accessUnit->meta()->setInt32("damaged", true);
150    }
151
152    mPackets.clear();
153    mAccessUnitDamaged = false;
154
155    sp<AMessage> msg = mNotifyMsg->dup();
156    msg->setObject("access-unit", accessUnit);
157    msg->post();
158}
159
160void AMPEG4AudioAssembler::packetLost() {
161    CHECK(mNextExpectedSeqNoValid);
162    ++mNextExpectedSeqNo;
163
164    mAccessUnitDamaged = true;
165}
166
167void AMPEG4AudioAssembler::onByeReceived() {
168    sp<AMessage> msg = mNotifyMsg->dup();
169    msg->setInt32("eos", true);
170    msg->post();
171}
172
173}  // namespace android
174