AMPEG4ElementaryAssembler.cpp revision 62cb04d23642a2ea7c005f050494c8ef3c370dd3
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 "AMPEG4ElementaryAssembler.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#include <media/stagefright/foundation/hexdump.h>
25
26#include <stdint.h>
27
28#define BE_VERBOSE      0
29
30namespace android {
31
32// static
33AMPEG4ElementaryAssembler::AMPEG4ElementaryAssembler(const sp<AMessage> &notify)
34    : mNotifyMsg(notify),
35      mAccessUnitRTPTime(0),
36      mNextExpectedSeqNoValid(false),
37      mNextExpectedSeqNo(0),
38      mAccessUnitDamaged(false) {
39}
40
41AMPEG4ElementaryAssembler::~AMPEG4ElementaryAssembler() {
42}
43
44ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::addPacket(
45        const sp<ARTPSource> &source) {
46    List<sp<ABuffer> > *queue = source->queue();
47
48    if (queue->empty()) {
49        return NOT_ENOUGH_DATA;
50    }
51
52    if (mNextExpectedSeqNoValid) {
53        List<sp<ABuffer> >::iterator it = queue->begin();
54        while (it != queue->end()) {
55            if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) {
56                break;
57            }
58
59            it = queue->erase(it);
60        }
61
62        if (queue->empty()) {
63            return NOT_ENOUGH_DATA;
64        }
65    }
66
67    sp<ABuffer> buffer = *queue->begin();
68
69    if (!mNextExpectedSeqNoValid) {
70        mNextExpectedSeqNoValid = true;
71        mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
72    } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
73#if BE_VERBOSE
74        LOG(VERBOSE) << "Not the sequence number I expected";
75#endif
76
77        return WRONG_SEQUENCE_NUMBER;
78    }
79
80    uint32_t rtpTime;
81    CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
82
83    if (mPackets.size() > 0 && rtpTime != mAccessUnitRTPTime) {
84        submitAccessUnit();
85    }
86    mAccessUnitRTPTime = rtpTime;
87
88    mPackets.push_back(buffer);
89    // hexdump(buffer->data(), buffer->size());
90
91    queue->erase(queue->begin());
92    ++mNextExpectedSeqNo;
93
94    return OK;
95}
96
97void AMPEG4ElementaryAssembler::submitAccessUnit() {
98    CHECK(!mPackets.empty());
99
100#if BE_VERBOSE
101    LOG(VERBOSE) << "Access unit complete (" << mPackets.size() << " nal units)";
102#endif
103
104    uint64_t ntpTime;
105    CHECK((*mPackets.begin())->meta()->findInt64(
106                "ntp-time", (int64_t *)&ntpTime));
107
108    size_t totalSize = 0;
109    for (List<sp<ABuffer> >::iterator it = mPackets.begin();
110         it != mPackets.end(); ++it) {
111        totalSize += (*it)->size();
112    }
113
114    sp<ABuffer> accessUnit = new ABuffer(totalSize);
115    size_t offset = 0;
116    for (List<sp<ABuffer> >::iterator it = mPackets.begin();
117         it != mPackets.end(); ++it) {
118        sp<ABuffer> nal = *it;
119        memcpy(accessUnit->data() + offset, nal->data(), nal->size());
120        offset += nal->size();
121    }
122
123    accessUnit->meta()->setInt64("ntp-time", ntpTime);
124
125#if 0
126    printf(mAccessUnitDamaged ? "X" : ".");
127    fflush(stdout);
128#endif
129
130    if (mAccessUnitDamaged) {
131        accessUnit->meta()->setInt32("damaged", true);
132    }
133
134    mPackets.clear();
135    mAccessUnitDamaged = false;
136
137    sp<AMessage> msg = mNotifyMsg->dup();
138    msg->setObject("access-unit", accessUnit);
139    msg->post();
140}
141
142ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::assembleMore(
143        const sp<ARTPSource> &source) {
144    AssemblyStatus status = addPacket(source);
145    if (status == MALFORMED_PACKET) {
146        mAccessUnitDamaged = true;
147    }
148    return status;
149}
150
151void AMPEG4ElementaryAssembler::packetLost() {
152    CHECK(mNextExpectedSeqNoValid);
153    LOG(VERBOSE) << "packetLost (expected " << mNextExpectedSeqNo << ")";
154
155    ++mNextExpectedSeqNo;
156
157    mAccessUnitDamaged = true;
158}
159
160void AMPEG4ElementaryAssembler::onByeReceived() {
161    sp<AMessage> msg = mNotifyMsg->dup();
162    msg->setInt32("eos", true);
163    msg->post();
164}
165
166}  // namespace android
167