xref: /aosp_15_r20/frameworks/av/media/module/mpeg2ts/ATSParser.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2010 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "ATSParser"
19*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
20*ec779b8eSAndroid Build Coastguard Worker #include "ATSParser.h"
21*ec779b8eSAndroid Build Coastguard Worker #include "AnotherPacketSource.h"
22*ec779b8eSAndroid Build Coastguard Worker #include "CasManager.h"
23*ec779b8eSAndroid Build Coastguard Worker #include "ESQueue.h"
24*ec779b8eSAndroid Build Coastguard Worker 
25*ec779b8eSAndroid Build Coastguard Worker #include <android/hardware/cas/native/1.0/IDescrambler.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <android/hidl/memory/1.0/IMemory.h>
27*ec779b8eSAndroid Build Coastguard Worker #include <cutils/ashmem.h>
28*ec779b8eSAndroid Build Coastguard Worker #include <cutils/native_handle.h>
29*ec779b8eSAndroid Build Coastguard Worker #include <hidlmemory/mapping.h>
30*ec779b8eSAndroid Build Coastguard Worker #include <media/cas/DescramblerAPI.h>
31*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ABitReader.h>
32*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ABuffer.h>
33*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ADebug.h>
34*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/AMessage.h>
35*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ByteUtils.h>
36*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/MediaKeys.h>
37*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/avc_utils.h>
38*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/hexdump.h>
39*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaDefs.h>
40*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaErrors.h>
41*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MetaData.h>
42*ec779b8eSAndroid Build Coastguard Worker #include <media/IStreamSource.h>
43*ec779b8eSAndroid Build Coastguard Worker #include <utils/KeyedVector.h>
44*ec779b8eSAndroid Build Coastguard Worker #include <utils/Vector.h>
45*ec779b8eSAndroid Build Coastguard Worker 
46*ec779b8eSAndroid Build Coastguard Worker #include <inttypes.h>
47*ec779b8eSAndroid Build Coastguard Worker 
48*ec779b8eSAndroid Build Coastguard Worker namespace android {
49*ec779b8eSAndroid Build Coastguard Worker using hardware::hidl_handle;
50*ec779b8eSAndroid Build Coastguard Worker using hardware::hidl_string;
51*ec779b8eSAndroid Build Coastguard Worker using hardware::hidl_vec;
52*ec779b8eSAndroid Build Coastguard Worker using hardware::hidl_memory;
53*ec779b8eSAndroid Build Coastguard Worker using namespace hardware::cas::V1_0;
54*ec779b8eSAndroid Build Coastguard Worker using namespace hardware::cas::native::V1_0;
55*ec779b8eSAndroid Build Coastguard Worker typedef hidl::memory::V1_0::IMemory TMemory;
56*ec779b8eSAndroid Build Coastguard Worker 
57*ec779b8eSAndroid Build Coastguard Worker // I want the expression "y" evaluated even if verbose logging is off.
58*ec779b8eSAndroid Build Coastguard Worker #define MY_LOGV(x, y) \
59*ec779b8eSAndroid Build Coastguard Worker     do { unsigned tmp = y; ALOGV(x, tmp); } while (0)
60*ec779b8eSAndroid Build Coastguard Worker 
61*ec779b8eSAndroid Build Coastguard Worker static const size_t kTSPacketSize = 188;
62*ec779b8eSAndroid Build Coastguard Worker 
63*ec779b8eSAndroid Build Coastguard Worker struct ATSParser::Program : public RefBase {
64*ec779b8eSAndroid Build Coastguard Worker     Program(ATSParser *parser, unsigned programNumber, unsigned programMapPID,
65*ec779b8eSAndroid Build Coastguard Worker             int64_t lastRecoveredPTS);
66*ec779b8eSAndroid Build Coastguard Worker 
67*ec779b8eSAndroid Build Coastguard Worker     bool parsePSISection(
68*ec779b8eSAndroid Build Coastguard Worker             unsigned pid, ABitReader *br, status_t *err);
69*ec779b8eSAndroid Build Coastguard Worker 
70*ec779b8eSAndroid Build Coastguard Worker     // Pass to appropriate stream according to pid, and set event if it's a PES
71*ec779b8eSAndroid Build Coastguard Worker     // with a sync frame.
72*ec779b8eSAndroid Build Coastguard Worker     // Note that the method itself does not touch event.
73*ec779b8eSAndroid Build Coastguard Worker     bool parsePID(
74*ec779b8eSAndroid Build Coastguard Worker             unsigned pid, unsigned continuity_counter,
75*ec779b8eSAndroid Build Coastguard Worker             unsigned payload_unit_start_indicator,
76*ec779b8eSAndroid Build Coastguard Worker             unsigned transport_scrambling_control,
77*ec779b8eSAndroid Build Coastguard Worker             unsigned random_access_indicator,
78*ec779b8eSAndroid Build Coastguard Worker             ABitReader *br, status_t *err, SyncEvent *event);
79*ec779b8eSAndroid Build Coastguard Worker 
80*ec779b8eSAndroid Build Coastguard Worker     void signalDiscontinuity(
81*ec779b8eSAndroid Build Coastguard Worker             DiscontinuityType type, const sp<AMessage> &extra);
82*ec779b8eSAndroid Build Coastguard Worker 
83*ec779b8eSAndroid Build Coastguard Worker     void signalEOS(status_t finalResult);
84*ec779b8eSAndroid Build Coastguard Worker 
85*ec779b8eSAndroid Build Coastguard Worker     sp<AnotherPacketSource> getSource(SourceType type);
86*ec779b8eSAndroid Build Coastguard Worker     bool hasSource(SourceType type) const;
87*ec779b8eSAndroid Build Coastguard Worker 
88*ec779b8eSAndroid Build Coastguard Worker     int64_t convertPTSToTimestamp(uint64_t PTS);
89*ec779b8eSAndroid Build Coastguard Worker 
PTSTimeDeltaEstablishedandroid::ATSParser::Program90*ec779b8eSAndroid Build Coastguard Worker     bool PTSTimeDeltaEstablished() const {
91*ec779b8eSAndroid Build Coastguard Worker         return mFirstPTSValid;
92*ec779b8eSAndroid Build Coastguard Worker     }
93*ec779b8eSAndroid Build Coastguard Worker 
numberandroid::ATSParser::Program94*ec779b8eSAndroid Build Coastguard Worker     unsigned number() const { return mProgramNumber; }
95*ec779b8eSAndroid Build Coastguard Worker 
updateProgramMapPIDandroid::ATSParser::Program96*ec779b8eSAndroid Build Coastguard Worker     void updateProgramMapPID(unsigned programMapPID) {
97*ec779b8eSAndroid Build Coastguard Worker         mProgramMapPID = programMapPID;
98*ec779b8eSAndroid Build Coastguard Worker     }
99*ec779b8eSAndroid Build Coastguard Worker 
programMapPIDandroid::ATSParser::Program100*ec779b8eSAndroid Build Coastguard Worker     unsigned programMapPID() const {
101*ec779b8eSAndroid Build Coastguard Worker         return mProgramMapPID;
102*ec779b8eSAndroid Build Coastguard Worker     }
103*ec779b8eSAndroid Build Coastguard Worker 
parserFlagsandroid::ATSParser::Program104*ec779b8eSAndroid Build Coastguard Worker     uint32_t parserFlags() const {
105*ec779b8eSAndroid Build Coastguard Worker         return mParser->mFlags;
106*ec779b8eSAndroid Build Coastguard Worker     }
107*ec779b8eSAndroid Build Coastguard Worker 
casManagerandroid::ATSParser::Program108*ec779b8eSAndroid Build Coastguard Worker     sp<CasManager> casManager() const {
109*ec779b8eSAndroid Build Coastguard Worker         return mParser->mCasManager;
110*ec779b8eSAndroid Build Coastguard Worker     }
111*ec779b8eSAndroid Build Coastguard Worker 
firstPTSandroid::ATSParser::Program112*ec779b8eSAndroid Build Coastguard Worker     uint64_t firstPTS() const {
113*ec779b8eSAndroid Build Coastguard Worker         return mFirstPTS;
114*ec779b8eSAndroid Build Coastguard Worker     }
115*ec779b8eSAndroid Build Coastguard Worker 
116*ec779b8eSAndroid Build Coastguard Worker     void updateCasSessions();
117*ec779b8eSAndroid Build Coastguard Worker 
118*ec779b8eSAndroid Build Coastguard Worker     void signalNewSampleAesKey(const sp<AMessage> &keyItem);
119*ec779b8eSAndroid Build Coastguard Worker 
120*ec779b8eSAndroid Build Coastguard Worker private:
121*ec779b8eSAndroid Build Coastguard Worker 
122*ec779b8eSAndroid Build Coastguard Worker     ATSParser *mParser;
123*ec779b8eSAndroid Build Coastguard Worker     unsigned mProgramNumber;
124*ec779b8eSAndroid Build Coastguard Worker     unsigned mProgramMapPID;
125*ec779b8eSAndroid Build Coastguard Worker     uint32_t mPMTVersion;
126*ec779b8eSAndroid Build Coastguard Worker     uint32_t mPMT_CRC;
127*ec779b8eSAndroid Build Coastguard Worker     KeyedVector<unsigned, sp<Stream> > mStreams;
128*ec779b8eSAndroid Build Coastguard Worker     bool mFirstPTSValid;
129*ec779b8eSAndroid Build Coastguard Worker     uint64_t mFirstPTS;
130*ec779b8eSAndroid Build Coastguard Worker     int64_t mLastRecoveredPTS;
131*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> mSampleAesKeyItem;
132*ec779b8eSAndroid Build Coastguard Worker 
133*ec779b8eSAndroid Build Coastguard Worker     status_t parseProgramMap(ABitReader *br);
134*ec779b8eSAndroid Build Coastguard Worker     int64_t recoverPTS(uint64_t PTS_33bit);
135*ec779b8eSAndroid Build Coastguard Worker     bool findCADescriptor(
136*ec779b8eSAndroid Build Coastguard Worker             ABitReader *br, unsigned infoLength, CADescriptor *caDescriptor);
137*ec779b8eSAndroid Build Coastguard Worker     bool switchPIDs(const Vector<StreamInfo> &infos);
138*ec779b8eSAndroid Build Coastguard Worker 
139*ec779b8eSAndroid Build Coastguard Worker     DISALLOW_EVIL_CONSTRUCTORS(Program);
140*ec779b8eSAndroid Build Coastguard Worker };
141*ec779b8eSAndroid Build Coastguard Worker 
142*ec779b8eSAndroid Build Coastguard Worker struct ATSParser::Stream : public RefBase {
143*ec779b8eSAndroid Build Coastguard Worker     Stream(Program *program, unsigned PCR_PID, const StreamInfo &info);
144*ec779b8eSAndroid Build Coastguard Worker 
typeandroid::ATSParser::Stream145*ec779b8eSAndroid Build Coastguard Worker     unsigned type() const { return mStreamType; }
typeExtandroid::ATSParser::Stream146*ec779b8eSAndroid Build Coastguard Worker     unsigned typeExt() const { return mStreamTypeExt; }
pidandroid::ATSParser::Stream147*ec779b8eSAndroid Build Coastguard Worker     unsigned pid() const { return mElementaryPID; }
setPIDandroid::ATSParser::Stream148*ec779b8eSAndroid Build Coastguard Worker     void setPID(unsigned pid) { mElementaryPID = pid; }
setAudioPresentationsandroid::ATSParser::Stream149*ec779b8eSAndroid Build Coastguard Worker     void setAudioPresentations(AudioPresentationCollection audioPresentations) {
150*ec779b8eSAndroid Build Coastguard Worker         mAudioPresentations = audioPresentations;
151*ec779b8eSAndroid Build Coastguard Worker     }
152*ec779b8eSAndroid Build Coastguard Worker 
153*ec779b8eSAndroid Build Coastguard Worker     void setCasInfo(
154*ec779b8eSAndroid Build Coastguard Worker             int32_t systemId,
155*ec779b8eSAndroid Build Coastguard Worker             const sp<IDescrambler> &descrambler,
156*ec779b8eSAndroid Build Coastguard Worker             const std::vector<uint8_t> &sessionId);
157*ec779b8eSAndroid Build Coastguard Worker 
158*ec779b8eSAndroid Build Coastguard Worker     // Parse the payload and set event when PES with a sync frame is detected.
159*ec779b8eSAndroid Build Coastguard Worker     // This method knows when a PES starts; so record mPesStartOffsets in that
160*ec779b8eSAndroid Build Coastguard Worker     // case.
161*ec779b8eSAndroid Build Coastguard Worker     status_t parse(
162*ec779b8eSAndroid Build Coastguard Worker             unsigned continuity_counter,
163*ec779b8eSAndroid Build Coastguard Worker             unsigned payload_unit_start_indicator,
164*ec779b8eSAndroid Build Coastguard Worker             unsigned transport_scrambling_control,
165*ec779b8eSAndroid Build Coastguard Worker             unsigned random_access_indicator,
166*ec779b8eSAndroid Build Coastguard Worker             ABitReader *br,
167*ec779b8eSAndroid Build Coastguard Worker             SyncEvent *event);
168*ec779b8eSAndroid Build Coastguard Worker 
169*ec779b8eSAndroid Build Coastguard Worker     void signalDiscontinuity(
170*ec779b8eSAndroid Build Coastguard Worker             DiscontinuityType type, const sp<AMessage> &extra);
171*ec779b8eSAndroid Build Coastguard Worker 
172*ec779b8eSAndroid Build Coastguard Worker     void signalEOS(status_t finalResult);
173*ec779b8eSAndroid Build Coastguard Worker 
174*ec779b8eSAndroid Build Coastguard Worker     SourceType getSourceType();
175*ec779b8eSAndroid Build Coastguard Worker     sp<AnotherPacketSource> getSource(SourceType type);
176*ec779b8eSAndroid Build Coastguard Worker 
177*ec779b8eSAndroid Build Coastguard Worker     bool isAudio() const;
178*ec779b8eSAndroid Build Coastguard Worker     bool isVideo() const;
179*ec779b8eSAndroid Build Coastguard Worker     bool isMeta() const;
180*ec779b8eSAndroid Build Coastguard Worker 
181*ec779b8eSAndroid Build Coastguard Worker     void signalNewSampleAesKey(const sp<AMessage> &keyItem);
182*ec779b8eSAndroid Build Coastguard Worker 
183*ec779b8eSAndroid Build Coastguard Worker protected:
184*ec779b8eSAndroid Build Coastguard Worker     virtual ~Stream();
185*ec779b8eSAndroid Build Coastguard Worker 
186*ec779b8eSAndroid Build Coastguard Worker private:
187*ec779b8eSAndroid Build Coastguard Worker     struct SubSampleInfo {
188*ec779b8eSAndroid Build Coastguard Worker         size_t subSampleSize;
189*ec779b8eSAndroid Build Coastguard Worker         unsigned transport_scrambling_mode;
190*ec779b8eSAndroid Build Coastguard Worker         unsigned random_access_indicator;
191*ec779b8eSAndroid Build Coastguard Worker     };
192*ec779b8eSAndroid Build Coastguard Worker     Program *mProgram;
193*ec779b8eSAndroid Build Coastguard Worker     unsigned mElementaryPID;
194*ec779b8eSAndroid Build Coastguard Worker     unsigned mStreamType;
195*ec779b8eSAndroid Build Coastguard Worker     unsigned mStreamTypeExt;
196*ec779b8eSAndroid Build Coastguard Worker     unsigned mPCR_PID;
197*ec779b8eSAndroid Build Coastguard Worker     int32_t mExpectedContinuityCounter;
198*ec779b8eSAndroid Build Coastguard Worker 
199*ec779b8eSAndroid Build Coastguard Worker     sp<ABuffer> mBuffer;
200*ec779b8eSAndroid Build Coastguard Worker     sp<AnotherPacketSource> mSource;
201*ec779b8eSAndroid Build Coastguard Worker     bool mPayloadStarted;
202*ec779b8eSAndroid Build Coastguard Worker     bool mEOSReached;
203*ec779b8eSAndroid Build Coastguard Worker 
204*ec779b8eSAndroid Build Coastguard Worker     uint64_t mPrevPTS;
205*ec779b8eSAndroid Build Coastguard Worker     List<off64_t> mPesStartOffsets;
206*ec779b8eSAndroid Build Coastguard Worker 
207*ec779b8eSAndroid Build Coastguard Worker     ElementaryStreamQueue *mQueue;
208*ec779b8eSAndroid Build Coastguard Worker 
209*ec779b8eSAndroid Build Coastguard Worker     bool mScrambled;
210*ec779b8eSAndroid Build Coastguard Worker     bool mSampleEncrypted;
211*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> mSampleAesKeyItem;
212*ec779b8eSAndroid Build Coastguard Worker     sp<TMemory> mHidlMemory;
213*ec779b8eSAndroid Build Coastguard Worker     hardware::cas::native::V1_0::SharedBuffer mDescramblerSrcBuffer;
214*ec779b8eSAndroid Build Coastguard Worker     sp<ABuffer> mDescrambledBuffer;
215*ec779b8eSAndroid Build Coastguard Worker     List<SubSampleInfo> mSubSamples;
216*ec779b8eSAndroid Build Coastguard Worker     sp<IDescrambler> mDescrambler;
217*ec779b8eSAndroid Build Coastguard Worker     AudioPresentationCollection mAudioPresentations;
218*ec779b8eSAndroid Build Coastguard Worker 
219*ec779b8eSAndroid Build Coastguard Worker     // Send audio presentations along with access units.
220*ec779b8eSAndroid Build Coastguard Worker     void addAudioPresentations(const sp<ABuffer> &buffer);
221*ec779b8eSAndroid Build Coastguard Worker 
222*ec779b8eSAndroid Build Coastguard Worker     // Flush accumulated payload if necessary --- i.e. at EOS or at the start of
223*ec779b8eSAndroid Build Coastguard Worker     // another payload. event is set if the flushed payload is PES with a sync
224*ec779b8eSAndroid Build Coastguard Worker     // frame.
225*ec779b8eSAndroid Build Coastguard Worker     status_t flush(SyncEvent *event);
226*ec779b8eSAndroid Build Coastguard Worker 
227*ec779b8eSAndroid Build Coastguard Worker     // Flush accumulated payload for scrambled streams if necessary --- i.e. at
228*ec779b8eSAndroid Build Coastguard Worker     // EOS or at the start of another payload. event is set if the flushed
229*ec779b8eSAndroid Build Coastguard Worker     // payload is PES with a sync frame.
230*ec779b8eSAndroid Build Coastguard Worker     status_t flushScrambled(SyncEvent *event);
231*ec779b8eSAndroid Build Coastguard Worker 
232*ec779b8eSAndroid Build Coastguard Worker     // Check if a PES packet is scrambled at PES level.
233*ec779b8eSAndroid Build Coastguard Worker     uint32_t getPesScramblingControl(ABitReader *br, int32_t *pesOffset);
234*ec779b8eSAndroid Build Coastguard Worker 
235*ec779b8eSAndroid Build Coastguard Worker     // Strip and parse PES headers and pass remaining payload into onPayload
236*ec779b8eSAndroid Build Coastguard Worker     // with parsed metadata. event is set if the PES contains a sync frame.
237*ec779b8eSAndroid Build Coastguard Worker     status_t parsePES(ABitReader *br, SyncEvent *event);
238*ec779b8eSAndroid Build Coastguard Worker 
239*ec779b8eSAndroid Build Coastguard Worker     // Feed the payload into mQueue and if a packet is identified, queue it
240*ec779b8eSAndroid Build Coastguard Worker     // into mSource. If the packet is a sync frame. set event with start offset
241*ec779b8eSAndroid Build Coastguard Worker     // and timestamp of the packet.
242*ec779b8eSAndroid Build Coastguard Worker     void onPayloadData(
243*ec779b8eSAndroid Build Coastguard Worker             unsigned PTS_DTS_flags, uint64_t PTS, uint64_t DTS,
244*ec779b8eSAndroid Build Coastguard Worker             unsigned PES_scrambling_control,
245*ec779b8eSAndroid Build Coastguard Worker             const uint8_t *data, size_t size,
246*ec779b8eSAndroid Build Coastguard Worker             int32_t payloadOffset, SyncEvent *event);
247*ec779b8eSAndroid Build Coastguard Worker 
248*ec779b8eSAndroid Build Coastguard Worker     // Ensure internal buffers can hold specified size, and will re-allocate
249*ec779b8eSAndroid Build Coastguard Worker     // as needed.
250*ec779b8eSAndroid Build Coastguard Worker     bool ensureBufferCapacity(size_t size);
251*ec779b8eSAndroid Build Coastguard Worker 
252*ec779b8eSAndroid Build Coastguard Worker     DISALLOW_EVIL_CONSTRUCTORS(Stream);
253*ec779b8eSAndroid Build Coastguard Worker };
254*ec779b8eSAndroid Build Coastguard Worker 
255*ec779b8eSAndroid Build Coastguard Worker struct ATSParser::PSISection : public RefBase {
256*ec779b8eSAndroid Build Coastguard Worker     PSISection();
257*ec779b8eSAndroid Build Coastguard Worker 
258*ec779b8eSAndroid Build Coastguard Worker     status_t append(const void *data, size_t size);
259*ec779b8eSAndroid Build Coastguard Worker     void setSkipBytes(uint8_t skip);
260*ec779b8eSAndroid Build Coastguard Worker     void clear();
261*ec779b8eSAndroid Build Coastguard Worker 
262*ec779b8eSAndroid Build Coastguard Worker     bool isComplete() const;
263*ec779b8eSAndroid Build Coastguard Worker     bool isEmpty() const;
264*ec779b8eSAndroid Build Coastguard Worker     bool isCRCOkay() const;
265*ec779b8eSAndroid Build Coastguard Worker 
266*ec779b8eSAndroid Build Coastguard Worker     const uint8_t *data() const;
267*ec779b8eSAndroid Build Coastguard Worker     size_t size() const;
268*ec779b8eSAndroid Build Coastguard Worker 
269*ec779b8eSAndroid Build Coastguard Worker protected:
270*ec779b8eSAndroid Build Coastguard Worker     virtual ~PSISection();
271*ec779b8eSAndroid Build Coastguard Worker 
272*ec779b8eSAndroid Build Coastguard Worker private:
273*ec779b8eSAndroid Build Coastguard Worker     sp<ABuffer> mBuffer;
274*ec779b8eSAndroid Build Coastguard Worker     uint8_t mSkipBytes;
275*ec779b8eSAndroid Build Coastguard Worker     static uint32_t CRC_TABLE[];
276*ec779b8eSAndroid Build Coastguard Worker 
277*ec779b8eSAndroid Build Coastguard Worker     DISALLOW_EVIL_CONSTRUCTORS(PSISection);
278*ec779b8eSAndroid Build Coastguard Worker };
279*ec779b8eSAndroid Build Coastguard Worker 
SyncEvent(off64_t offset)280*ec779b8eSAndroid Build Coastguard Worker ATSParser::SyncEvent::SyncEvent(off64_t offset)
281*ec779b8eSAndroid Build Coastguard Worker     : mHasReturnedData(false), mOffset(offset), mTimeUs(0) {}
282*ec779b8eSAndroid Build Coastguard Worker 
init(off64_t offset,const sp<AnotherPacketSource> & source,int64_t timeUs,SourceType type)283*ec779b8eSAndroid Build Coastguard Worker void ATSParser::SyncEvent::init(off64_t offset, const sp<AnotherPacketSource> &source,
284*ec779b8eSAndroid Build Coastguard Worker         int64_t timeUs, SourceType type) {
285*ec779b8eSAndroid Build Coastguard Worker     mHasReturnedData = true;
286*ec779b8eSAndroid Build Coastguard Worker     mOffset = offset;
287*ec779b8eSAndroid Build Coastguard Worker     mMediaSource = source;
288*ec779b8eSAndroid Build Coastguard Worker     mTimeUs = timeUs;
289*ec779b8eSAndroid Build Coastguard Worker     mType = type;
290*ec779b8eSAndroid Build Coastguard Worker }
291*ec779b8eSAndroid Build Coastguard Worker 
reset()292*ec779b8eSAndroid Build Coastguard Worker void ATSParser::SyncEvent::reset() {
293*ec779b8eSAndroid Build Coastguard Worker     mHasReturnedData = false;
294*ec779b8eSAndroid Build Coastguard Worker }
295*ec779b8eSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
296*ec779b8eSAndroid Build Coastguard Worker 
Program(ATSParser * parser,unsigned programNumber,unsigned programMapPID,int64_t lastRecoveredPTS)297*ec779b8eSAndroid Build Coastguard Worker ATSParser::Program::Program(
298*ec779b8eSAndroid Build Coastguard Worker         ATSParser *parser, unsigned programNumber, unsigned programMapPID,
299*ec779b8eSAndroid Build Coastguard Worker         int64_t lastRecoveredPTS)
300*ec779b8eSAndroid Build Coastguard Worker     : mParser(parser),
301*ec779b8eSAndroid Build Coastguard Worker       mProgramNumber(programNumber),
302*ec779b8eSAndroid Build Coastguard Worker       mProgramMapPID(programMapPID),
303*ec779b8eSAndroid Build Coastguard Worker       mPMTVersion(0xffffffff),
304*ec779b8eSAndroid Build Coastguard Worker       mPMT_CRC(0xffffffff),
305*ec779b8eSAndroid Build Coastguard Worker       mFirstPTSValid(false),
306*ec779b8eSAndroid Build Coastguard Worker       mFirstPTS(0),
307*ec779b8eSAndroid Build Coastguard Worker       mLastRecoveredPTS(lastRecoveredPTS) {
308*ec779b8eSAndroid Build Coastguard Worker     ALOGV("new program number %u", programNumber);
309*ec779b8eSAndroid Build Coastguard Worker }
310*ec779b8eSAndroid Build Coastguard Worker 
parsePSISection(unsigned pid,ABitReader * br,status_t * err)311*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::Program::parsePSISection(
312*ec779b8eSAndroid Build Coastguard Worker         unsigned pid, ABitReader *br, status_t *err) {
313*ec779b8eSAndroid Build Coastguard Worker     *err = OK;
314*ec779b8eSAndroid Build Coastguard Worker 
315*ec779b8eSAndroid Build Coastguard Worker     if (pid != mProgramMapPID) {
316*ec779b8eSAndroid Build Coastguard Worker         return false;
317*ec779b8eSAndroid Build Coastguard Worker     }
318*ec779b8eSAndroid Build Coastguard Worker 
319*ec779b8eSAndroid Build Coastguard Worker     *err = parseProgramMap(br);
320*ec779b8eSAndroid Build Coastguard Worker 
321*ec779b8eSAndroid Build Coastguard Worker     return true;
322*ec779b8eSAndroid Build Coastguard Worker }
323*ec779b8eSAndroid Build Coastguard Worker 
parsePID(unsigned pid,unsigned continuity_counter,unsigned payload_unit_start_indicator,unsigned transport_scrambling_control,unsigned random_access_indicator,ABitReader * br,status_t * err,SyncEvent * event)324*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::Program::parsePID(
325*ec779b8eSAndroid Build Coastguard Worker         unsigned pid, unsigned continuity_counter,
326*ec779b8eSAndroid Build Coastguard Worker         unsigned payload_unit_start_indicator,
327*ec779b8eSAndroid Build Coastguard Worker         unsigned transport_scrambling_control,
328*ec779b8eSAndroid Build Coastguard Worker         unsigned random_access_indicator,
329*ec779b8eSAndroid Build Coastguard Worker         ABitReader *br, status_t *err, SyncEvent *event) {
330*ec779b8eSAndroid Build Coastguard Worker     *err = OK;
331*ec779b8eSAndroid Build Coastguard Worker 
332*ec779b8eSAndroid Build Coastguard Worker     ssize_t index = mStreams.indexOfKey(pid);
333*ec779b8eSAndroid Build Coastguard Worker     if (index < 0) {
334*ec779b8eSAndroid Build Coastguard Worker         return false;
335*ec779b8eSAndroid Build Coastguard Worker     }
336*ec779b8eSAndroid Build Coastguard Worker 
337*ec779b8eSAndroid Build Coastguard Worker     *err = mStreams.editValueAt(index)->parse(
338*ec779b8eSAndroid Build Coastguard Worker             continuity_counter,
339*ec779b8eSAndroid Build Coastguard Worker             payload_unit_start_indicator,
340*ec779b8eSAndroid Build Coastguard Worker             transport_scrambling_control,
341*ec779b8eSAndroid Build Coastguard Worker             random_access_indicator,
342*ec779b8eSAndroid Build Coastguard Worker             br, event);
343*ec779b8eSAndroid Build Coastguard Worker 
344*ec779b8eSAndroid Build Coastguard Worker     return true;
345*ec779b8eSAndroid Build Coastguard Worker }
346*ec779b8eSAndroid Build Coastguard Worker 
signalDiscontinuity(DiscontinuityType type,const sp<AMessage> & extra)347*ec779b8eSAndroid Build Coastguard Worker void ATSParser::Program::signalDiscontinuity(
348*ec779b8eSAndroid Build Coastguard Worker         DiscontinuityType type, const sp<AMessage> &extra) {
349*ec779b8eSAndroid Build Coastguard Worker     int64_t mediaTimeUs;
350*ec779b8eSAndroid Build Coastguard Worker     if ((type & DISCONTINUITY_TIME)
351*ec779b8eSAndroid Build Coastguard Worker             && extra != NULL
352*ec779b8eSAndroid Build Coastguard Worker             && extra->findInt64(
353*ec779b8eSAndroid Build Coastguard Worker                 kATSParserKeyMediaTimeUs, &mediaTimeUs)) {
354*ec779b8eSAndroid Build Coastguard Worker         mFirstPTSValid = false;
355*ec779b8eSAndroid Build Coastguard Worker     }
356*ec779b8eSAndroid Build Coastguard Worker 
357*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < mStreams.size(); ++i) {
358*ec779b8eSAndroid Build Coastguard Worker         mStreams.editValueAt(i)->signalDiscontinuity(type, extra);
359*ec779b8eSAndroid Build Coastguard Worker     }
360*ec779b8eSAndroid Build Coastguard Worker }
361*ec779b8eSAndroid Build Coastguard Worker 
signalEOS(status_t finalResult)362*ec779b8eSAndroid Build Coastguard Worker void ATSParser::Program::signalEOS(status_t finalResult) {
363*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < mStreams.size(); ++i) {
364*ec779b8eSAndroid Build Coastguard Worker         mStreams.editValueAt(i)->signalEOS(finalResult);
365*ec779b8eSAndroid Build Coastguard Worker     }
366*ec779b8eSAndroid Build Coastguard Worker }
367*ec779b8eSAndroid Build Coastguard Worker 
switchPIDs(const Vector<StreamInfo> & infos)368*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::Program::switchPIDs(const Vector<StreamInfo> &infos) {
369*ec779b8eSAndroid Build Coastguard Worker     bool success = false;
370*ec779b8eSAndroid Build Coastguard Worker 
371*ec779b8eSAndroid Build Coastguard Worker     if (mStreams.size() == infos.size()) {
372*ec779b8eSAndroid Build Coastguard Worker         // build type->PIDs map for old and new mapping
373*ec779b8eSAndroid Build Coastguard Worker         size_t i;
374*ec779b8eSAndroid Build Coastguard Worker         KeyedVector<int32_t, Vector<int32_t> > oldType2PIDs, newType2PIDs;
375*ec779b8eSAndroid Build Coastguard Worker         for (i = 0; i < mStreams.size(); ++i) {
376*ec779b8eSAndroid Build Coastguard Worker             ssize_t index = oldType2PIDs.indexOfKey(mStreams[i]->type());
377*ec779b8eSAndroid Build Coastguard Worker             if (index < 0) {
378*ec779b8eSAndroid Build Coastguard Worker                 oldType2PIDs.add(mStreams[i]->type(), Vector<int32_t>());
379*ec779b8eSAndroid Build Coastguard Worker             }
380*ec779b8eSAndroid Build Coastguard Worker             oldType2PIDs.editValueFor(mStreams[i]->type()).push_back(mStreams[i]->pid());
381*ec779b8eSAndroid Build Coastguard Worker         }
382*ec779b8eSAndroid Build Coastguard Worker         for (i = 0; i < infos.size(); ++i) {
383*ec779b8eSAndroid Build Coastguard Worker             ssize_t index = newType2PIDs.indexOfKey(infos[i].mType);
384*ec779b8eSAndroid Build Coastguard Worker             if (index < 0) {
385*ec779b8eSAndroid Build Coastguard Worker                 newType2PIDs.add(infos[i].mType, Vector<int32_t>());
386*ec779b8eSAndroid Build Coastguard Worker             }
387*ec779b8eSAndroid Build Coastguard Worker             newType2PIDs.editValueFor(infos[i].mType).push_back(infos[i].mPID);
388*ec779b8eSAndroid Build Coastguard Worker         }
389*ec779b8eSAndroid Build Coastguard Worker 
390*ec779b8eSAndroid Build Coastguard Worker         // we can recover if the number of streams for each type hasn't changed
391*ec779b8eSAndroid Build Coastguard Worker         if (oldType2PIDs.size() == newType2PIDs.size()) {
392*ec779b8eSAndroid Build Coastguard Worker             success = true;
393*ec779b8eSAndroid Build Coastguard Worker             for (i = 0; i < oldType2PIDs.size(); ++i) {
394*ec779b8eSAndroid Build Coastguard Worker                 // KeyedVector is sorted, we just compare key and size of each index
395*ec779b8eSAndroid Build Coastguard Worker                 if (oldType2PIDs.keyAt(i) != newType2PIDs.keyAt(i)
396*ec779b8eSAndroid Build Coastguard Worker                         || oldType2PIDs[i].size() != newType2PIDs[i].size()) {
397*ec779b8eSAndroid Build Coastguard Worker                      success = false;
398*ec779b8eSAndroid Build Coastguard Worker                      break;
399*ec779b8eSAndroid Build Coastguard Worker                 }
400*ec779b8eSAndroid Build Coastguard Worker             }
401*ec779b8eSAndroid Build Coastguard Worker         }
402*ec779b8eSAndroid Build Coastguard Worker 
403*ec779b8eSAndroid Build Coastguard Worker         if (success) {
404*ec779b8eSAndroid Build Coastguard Worker             // save current streams to temp
405*ec779b8eSAndroid Build Coastguard Worker             KeyedVector<int32_t, sp<Stream> > temp;
406*ec779b8eSAndroid Build Coastguard Worker             for (i = 0; i < mStreams.size(); ++i) {
407*ec779b8eSAndroid Build Coastguard Worker                  temp.add(mStreams.keyAt(i), mStreams.editValueAt(i));
408*ec779b8eSAndroid Build Coastguard Worker             }
409*ec779b8eSAndroid Build Coastguard Worker 
410*ec779b8eSAndroid Build Coastguard Worker             mStreams.clear();
411*ec779b8eSAndroid Build Coastguard Worker             for (i = 0; i < temp.size(); ++i) {
412*ec779b8eSAndroid Build Coastguard Worker                 // The two checks below shouldn't happen,
413*ec779b8eSAndroid Build Coastguard Worker                 // we already checked above the stream count matches
414*ec779b8eSAndroid Build Coastguard Worker                 ssize_t index = newType2PIDs.indexOfKey(temp[i]->type());
415*ec779b8eSAndroid Build Coastguard Worker                 if (index < 0) {
416*ec779b8eSAndroid Build Coastguard Worker                     return false;
417*ec779b8eSAndroid Build Coastguard Worker                 }
418*ec779b8eSAndroid Build Coastguard Worker                 Vector<int32_t> &newPIDs = newType2PIDs.editValueAt(index);
419*ec779b8eSAndroid Build Coastguard Worker                 if (newPIDs.isEmpty()) {
420*ec779b8eSAndroid Build Coastguard Worker                     return false;
421*ec779b8eSAndroid Build Coastguard Worker                 }
422*ec779b8eSAndroid Build Coastguard Worker 
423*ec779b8eSAndroid Build Coastguard Worker                 // get the next PID for temp[i]->type() in the new PID map
424*ec779b8eSAndroid Build Coastguard Worker                 Vector<int32_t>::iterator it = newPIDs.begin();
425*ec779b8eSAndroid Build Coastguard Worker 
426*ec779b8eSAndroid Build Coastguard Worker                 // change the PID of the stream, and add it back
427*ec779b8eSAndroid Build Coastguard Worker                 temp.editValueAt(i)->setPID(*it);
428*ec779b8eSAndroid Build Coastguard Worker                 mStreams.add(temp[i]->pid(), temp.editValueAt(i));
429*ec779b8eSAndroid Build Coastguard Worker 
430*ec779b8eSAndroid Build Coastguard Worker                 // removed the used PID
431*ec779b8eSAndroid Build Coastguard Worker                 newPIDs.erase(it);
432*ec779b8eSAndroid Build Coastguard Worker             }
433*ec779b8eSAndroid Build Coastguard Worker         }
434*ec779b8eSAndroid Build Coastguard Worker     }
435*ec779b8eSAndroid Build Coastguard Worker     return success;
436*ec779b8eSAndroid Build Coastguard Worker }
437*ec779b8eSAndroid Build Coastguard Worker 
findCADescriptor(ABitReader * br,unsigned infoLength,ATSParser::CADescriptor * caDescriptor)438*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::Program::findCADescriptor(
439*ec779b8eSAndroid Build Coastguard Worker         ABitReader *br, unsigned infoLength,
440*ec779b8eSAndroid Build Coastguard Worker         ATSParser::CADescriptor *caDescriptor) {
441*ec779b8eSAndroid Build Coastguard Worker     bool found = false;
442*ec779b8eSAndroid Build Coastguard Worker     while (infoLength > 2) {
443*ec779b8eSAndroid Build Coastguard Worker         if (br->numBitsLeft() < 16) {
444*ec779b8eSAndroid Build Coastguard Worker             ALOGE("Not enough data left in bitreader");
445*ec779b8eSAndroid Build Coastguard Worker             return false;
446*ec779b8eSAndroid Build Coastguard Worker         }
447*ec779b8eSAndroid Build Coastguard Worker         unsigned descriptor_tag = br->getBits(8);
448*ec779b8eSAndroid Build Coastguard Worker         ALOGV("      tag = 0x%02x", descriptor_tag);
449*ec779b8eSAndroid Build Coastguard Worker 
450*ec779b8eSAndroid Build Coastguard Worker         unsigned descriptor_length = br->getBits(8);
451*ec779b8eSAndroid Build Coastguard Worker         ALOGV("      len = %u", descriptor_length);
452*ec779b8eSAndroid Build Coastguard Worker 
453*ec779b8eSAndroid Build Coastguard Worker         infoLength -= 2;
454*ec779b8eSAndroid Build Coastguard Worker         if (descriptor_length > infoLength) {
455*ec779b8eSAndroid Build Coastguard Worker             break;
456*ec779b8eSAndroid Build Coastguard Worker         }
457*ec779b8eSAndroid Build Coastguard Worker         if (descriptor_tag == DESCRIPTOR_CA && descriptor_length >= 4) {
458*ec779b8eSAndroid Build Coastguard Worker             found = true;
459*ec779b8eSAndroid Build Coastguard Worker             if (br->numBitsLeft() < 32) {
460*ec779b8eSAndroid Build Coastguard Worker                 ALOGE("Not enough data left in bitreader");
461*ec779b8eSAndroid Build Coastguard Worker                 return false;
462*ec779b8eSAndroid Build Coastguard Worker             }
463*ec779b8eSAndroid Build Coastguard Worker             caDescriptor->mSystemID = br->getBits(16);
464*ec779b8eSAndroid Build Coastguard Worker             caDescriptor->mPID = br->getBits(16) & 0x1fff;
465*ec779b8eSAndroid Build Coastguard Worker             infoLength -= 4;
466*ec779b8eSAndroid Build Coastguard Worker             caDescriptor->mPrivateData.assign(
467*ec779b8eSAndroid Build Coastguard Worker                     br->data(), br->data() + descriptor_length - 4);
468*ec779b8eSAndroid Build Coastguard Worker             break;
469*ec779b8eSAndroid Build Coastguard Worker         } else {
470*ec779b8eSAndroid Build Coastguard Worker             infoLength -= descriptor_length;
471*ec779b8eSAndroid Build Coastguard Worker             if (!br->skipBits(descriptor_length * 8)) {
472*ec779b8eSAndroid Build Coastguard Worker                 ALOGE("Not enough data left in bitreader");
473*ec779b8eSAndroid Build Coastguard Worker                 return false;
474*ec779b8eSAndroid Build Coastguard Worker             }
475*ec779b8eSAndroid Build Coastguard Worker         }
476*ec779b8eSAndroid Build Coastguard Worker     }
477*ec779b8eSAndroid Build Coastguard Worker     if (!br->skipBits(infoLength * 8)) {
478*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Not enough data left in bitreader");
479*ec779b8eSAndroid Build Coastguard Worker         return false;
480*ec779b8eSAndroid Build Coastguard Worker     }
481*ec779b8eSAndroid Build Coastguard Worker     return found;
482*ec779b8eSAndroid Build Coastguard Worker }
483*ec779b8eSAndroid Build Coastguard Worker 
parseProgramMap(ABitReader * br)484*ec779b8eSAndroid Build Coastguard Worker status_t ATSParser::Program::parseProgramMap(ABitReader *br) {
485*ec779b8eSAndroid Build Coastguard Worker     if (br->numBitsLeft() < 10) {
486*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Not enough data left in bitreader!");
487*ec779b8eSAndroid Build Coastguard Worker         return ERROR_MALFORMED;
488*ec779b8eSAndroid Build Coastguard Worker     }
489*ec779b8eSAndroid Build Coastguard Worker     unsigned table_id = br->getBits(8);
490*ec779b8eSAndroid Build Coastguard Worker     ALOGV("  table_id = %u", table_id);
491*ec779b8eSAndroid Build Coastguard Worker     if (table_id != 0x02u) {
492*ec779b8eSAndroid Build Coastguard Worker         ALOGE("PMT data error!");
493*ec779b8eSAndroid Build Coastguard Worker         return ERROR_MALFORMED;
494*ec779b8eSAndroid Build Coastguard Worker     }
495*ec779b8eSAndroid Build Coastguard Worker     unsigned section_syntax_indicator = br->getBits(1);
496*ec779b8eSAndroid Build Coastguard Worker     ALOGV("  section_syntax_indicator = %u", section_syntax_indicator);
497*ec779b8eSAndroid Build Coastguard Worker     if (section_syntax_indicator != 1u) {
498*ec779b8eSAndroid Build Coastguard Worker         ALOGE("PMT data error!");
499*ec779b8eSAndroid Build Coastguard Worker         return ERROR_MALFORMED;
500*ec779b8eSAndroid Build Coastguard Worker     }
501*ec779b8eSAndroid Build Coastguard Worker 
502*ec779b8eSAndroid Build Coastguard Worker     br->skipBits(1);  // '0'
503*ec779b8eSAndroid Build Coastguard Worker     if (br->numBitsLeft() < 86) {
504*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Not enough data left in bitreader!");
505*ec779b8eSAndroid Build Coastguard Worker         return ERROR_MALFORMED;
506*ec779b8eSAndroid Build Coastguard Worker     }
507*ec779b8eSAndroid Build Coastguard Worker     MY_LOGV("  reserved = %u", br->getBits(2));
508*ec779b8eSAndroid Build Coastguard Worker 
509*ec779b8eSAndroid Build Coastguard Worker     unsigned section_length = br->getBits(12);
510*ec779b8eSAndroid Build Coastguard Worker     ALOGV("  section_length = %u", section_length);
511*ec779b8eSAndroid Build Coastguard Worker 
512*ec779b8eSAndroid Build Coastguard Worker     MY_LOGV("  program_number = %u", br->getBits(16));
513*ec779b8eSAndroid Build Coastguard Worker     MY_LOGV("  reserved = %u", br->getBits(2));
514*ec779b8eSAndroid Build Coastguard Worker     bool audioPresentationsChanged = false;
515*ec779b8eSAndroid Build Coastguard Worker     unsigned pmtVersion = br->getBits(5);
516*ec779b8eSAndroid Build Coastguard Worker     if (pmtVersion != mPMTVersion) {
517*ec779b8eSAndroid Build Coastguard Worker         audioPresentationsChanged = true;
518*ec779b8eSAndroid Build Coastguard Worker         mPMTVersion = pmtVersion;
519*ec779b8eSAndroid Build Coastguard Worker     }
520*ec779b8eSAndroid Build Coastguard Worker     MY_LOGV("  version_number = %u", pmtVersion);
521*ec779b8eSAndroid Build Coastguard Worker     MY_LOGV("  current_next_indicator = %u", br->getBits(1));
522*ec779b8eSAndroid Build Coastguard Worker     MY_LOGV("  section_number = %u", br->getBits(8));
523*ec779b8eSAndroid Build Coastguard Worker     MY_LOGV("  last_section_number = %u", br->getBits(8));
524*ec779b8eSAndroid Build Coastguard Worker     MY_LOGV("  reserved = %u", br->getBits(3));
525*ec779b8eSAndroid Build Coastguard Worker 
526*ec779b8eSAndroid Build Coastguard Worker     unsigned PCR_PID = br->getBits(13);
527*ec779b8eSAndroid Build Coastguard Worker     ALOGV("  PCR_PID = 0x%04x", PCR_PID);
528*ec779b8eSAndroid Build Coastguard Worker 
529*ec779b8eSAndroid Build Coastguard Worker     MY_LOGV("  reserved = %u", br->getBits(4));
530*ec779b8eSAndroid Build Coastguard Worker 
531*ec779b8eSAndroid Build Coastguard Worker     unsigned program_info_length = br->getBits(12);
532*ec779b8eSAndroid Build Coastguard Worker     ALOGV("  program_info_length = %u", program_info_length);
533*ec779b8eSAndroid Build Coastguard Worker 
534*ec779b8eSAndroid Build Coastguard Worker     // descriptors
535*ec779b8eSAndroid Build Coastguard Worker     CADescriptor programCA;
536*ec779b8eSAndroid Build Coastguard Worker     bool hasProgramCA = findCADescriptor(br, program_info_length, &programCA);
537*ec779b8eSAndroid Build Coastguard Worker     if (hasProgramCA && !mParser->mCasManager->addProgram(
538*ec779b8eSAndroid Build Coastguard Worker             mProgramNumber, programCA)) {
539*ec779b8eSAndroid Build Coastguard Worker         return ERROR_MALFORMED;
540*ec779b8eSAndroid Build Coastguard Worker     }
541*ec779b8eSAndroid Build Coastguard Worker 
542*ec779b8eSAndroid Build Coastguard Worker     Vector<StreamInfo> infos;
543*ec779b8eSAndroid Build Coastguard Worker 
544*ec779b8eSAndroid Build Coastguard Worker     // infoBytesRemaining is the number of bytes that make up the
545*ec779b8eSAndroid Build Coastguard Worker     // variable length section of ES_infos. It does not include the
546*ec779b8eSAndroid Build Coastguard Worker     // final CRC.
547*ec779b8eSAndroid Build Coastguard Worker     int32_t infoBytesRemaining = section_length - 9 - program_info_length - 4;
548*ec779b8eSAndroid Build Coastguard Worker 
549*ec779b8eSAndroid Build Coastguard Worker     while (infoBytesRemaining >= 5) {
550*ec779b8eSAndroid Build Coastguard Worker         StreamInfo info;
551*ec779b8eSAndroid Build Coastguard Worker         if (br->numBitsLeft() < 40) {
552*ec779b8eSAndroid Build Coastguard Worker             ALOGE("Not enough data left in bitreader!");
553*ec779b8eSAndroid Build Coastguard Worker             return ERROR_MALFORMED;
554*ec779b8eSAndroid Build Coastguard Worker         }
555*ec779b8eSAndroid Build Coastguard Worker         info.mType = br->getBits(8);
556*ec779b8eSAndroid Build Coastguard Worker         ALOGV("    stream_type = 0x%02x", info.mType);
557*ec779b8eSAndroid Build Coastguard Worker         MY_LOGV("    reserved = %u", br->getBits(3));
558*ec779b8eSAndroid Build Coastguard Worker 
559*ec779b8eSAndroid Build Coastguard Worker         info.mPID = br->getBits(13);
560*ec779b8eSAndroid Build Coastguard Worker         ALOGV("    elementary_PID = 0x%04x", info.mPID);
561*ec779b8eSAndroid Build Coastguard Worker 
562*ec779b8eSAndroid Build Coastguard Worker         MY_LOGV("    reserved = %u", br->getBits(4));
563*ec779b8eSAndroid Build Coastguard Worker 
564*ec779b8eSAndroid Build Coastguard Worker         unsigned ES_info_length = br->getBits(12);
565*ec779b8eSAndroid Build Coastguard Worker         ALOGV("    ES_info_length = %u", ES_info_length);
566*ec779b8eSAndroid Build Coastguard Worker         infoBytesRemaining -= 5 + ES_info_length;
567*ec779b8eSAndroid Build Coastguard Worker 
568*ec779b8eSAndroid Build Coastguard Worker         CADescriptor streamCA;
569*ec779b8eSAndroid Build Coastguard Worker         info.mTypeExt = EXT_DESCRIPTOR_DVB_RESERVED_MAX;
570*ec779b8eSAndroid Build Coastguard Worker 
571*ec779b8eSAndroid Build Coastguard Worker         info.mAudioPresentations.clear();
572*ec779b8eSAndroid Build Coastguard Worker         bool hasStreamCA = false;
573*ec779b8eSAndroid Build Coastguard Worker         while (ES_info_length > 2 && infoBytesRemaining >= 0) {
574*ec779b8eSAndroid Build Coastguard Worker             if (br->numBitsLeft() < 16) {
575*ec779b8eSAndroid Build Coastguard Worker                 ALOGE("Not enough data left in bitreader!");
576*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
577*ec779b8eSAndroid Build Coastguard Worker             }
578*ec779b8eSAndroid Build Coastguard Worker             unsigned descriptor_tag = br->getBits(8);
579*ec779b8eSAndroid Build Coastguard Worker             ALOGV("      tag = 0x%02x", descriptor_tag);
580*ec779b8eSAndroid Build Coastguard Worker 
581*ec779b8eSAndroid Build Coastguard Worker             unsigned descriptor_length = br->getBits(8);
582*ec779b8eSAndroid Build Coastguard Worker             ALOGV("      len = %u", descriptor_length);
583*ec779b8eSAndroid Build Coastguard Worker 
584*ec779b8eSAndroid Build Coastguard Worker             ES_info_length -= 2;
585*ec779b8eSAndroid Build Coastguard Worker             if (descriptor_length > ES_info_length) {
586*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
587*ec779b8eSAndroid Build Coastguard Worker             }
588*ec779b8eSAndroid Build Coastguard Worker 
589*ec779b8eSAndroid Build Coastguard Worker             // The DTS descriptor is used in the PSI PMT to identify streams which carry
590*ec779b8eSAndroid Build Coastguard Worker             // DTS audio(core only). If a DTS descriptor is present, a DTS-HD or DTS-UHD
591*ec779b8eSAndroid Build Coastguard Worker             // descriptors shall not be present in the same ES_info descriptor loop.
592*ec779b8eSAndroid Build Coastguard Worker             if (descriptor_tag == DESCRIPTOR_DTS) {
593*ec779b8eSAndroid Build Coastguard Worker                 info.mType = STREAMTYPE_DTS;
594*ec779b8eSAndroid Build Coastguard Worker                 ES_info_length -= descriptor_length;
595*ec779b8eSAndroid Build Coastguard Worker                 if (!br->skipBits(descriptor_length * 8)) {
596*ec779b8eSAndroid Build Coastguard Worker                     ALOGE("Not enough data left in bitreader!");
597*ec779b8eSAndroid Build Coastguard Worker                     return ERROR_MALFORMED;
598*ec779b8eSAndroid Build Coastguard Worker                 }
599*ec779b8eSAndroid Build Coastguard Worker             } else if (descriptor_tag == DESCRIPTOR_CA && descriptor_length >= 4) {
600*ec779b8eSAndroid Build Coastguard Worker                 hasStreamCA = true;
601*ec779b8eSAndroid Build Coastguard Worker                 if (br->numBitsLeft() < 32) {
602*ec779b8eSAndroid Build Coastguard Worker                     ALOGE("Not enough data left in bitreader!");
603*ec779b8eSAndroid Build Coastguard Worker                     return ERROR_MALFORMED;
604*ec779b8eSAndroid Build Coastguard Worker                 }
605*ec779b8eSAndroid Build Coastguard Worker                 streamCA.mSystemID = br->getBits(16);
606*ec779b8eSAndroid Build Coastguard Worker                 streamCA.mPID = br->getBits(16) & 0x1fff;
607*ec779b8eSAndroid Build Coastguard Worker                 ES_info_length -= descriptor_length;
608*ec779b8eSAndroid Build Coastguard Worker                 descriptor_length -= 4;
609*ec779b8eSAndroid Build Coastguard Worker                 streamCA.mPrivateData.assign(br->data(), br->data() + descriptor_length);
610*ec779b8eSAndroid Build Coastguard Worker                 if (!br->skipBits(descriptor_length * 8)) {
611*ec779b8eSAndroid Build Coastguard Worker                     ALOGE("Not enough data left in bitreader!");
612*ec779b8eSAndroid Build Coastguard Worker                     return ERROR_MALFORMED;
613*ec779b8eSAndroid Build Coastguard Worker                 }
614*ec779b8eSAndroid Build Coastguard Worker             } else if (info.mType == STREAMTYPE_PES_PRIVATE_DATA &&
615*ec779b8eSAndroid Build Coastguard Worker                        descriptor_tag == DESCRIPTOR_DVB_EXTENSION && descriptor_length >= 1) {
616*ec779b8eSAndroid Build Coastguard Worker                 if (br->numBitsLeft() < 8) {
617*ec779b8eSAndroid Build Coastguard Worker                     ALOGE("Not enough data left in bitreader!");
618*ec779b8eSAndroid Build Coastguard Worker                     return ERROR_MALFORMED;
619*ec779b8eSAndroid Build Coastguard Worker                 }
620*ec779b8eSAndroid Build Coastguard Worker                 unsigned descTagExt = br->getBits(8);
621*ec779b8eSAndroid Build Coastguard Worker                 ALOGV("      tag_ext = 0x%02x", descTagExt);
622*ec779b8eSAndroid Build Coastguard Worker                 ES_info_length -= descriptor_length;
623*ec779b8eSAndroid Build Coastguard Worker                 descriptor_length--;
624*ec779b8eSAndroid Build Coastguard Worker                 if (br->numBitsLeft() < (descriptor_length * 8)) {
625*ec779b8eSAndroid Build Coastguard Worker                     ALOGE("Not enough data left in bitreader!");
626*ec779b8eSAndroid Build Coastguard Worker                     return ERROR_MALFORMED;
627*ec779b8eSAndroid Build Coastguard Worker                 }
628*ec779b8eSAndroid Build Coastguard Worker                 // The AC4 descriptor is used in the PSI PMT to identify streams which carry AC4
629*ec779b8eSAndroid Build Coastguard Worker                 // audio.
630*ec779b8eSAndroid Build Coastguard Worker                 if (descTagExt == EXT_DESCRIPTOR_DVB_AC4) {
631*ec779b8eSAndroid Build Coastguard Worker                     info.mTypeExt = EXT_DESCRIPTOR_DVB_AC4;
632*ec779b8eSAndroid Build Coastguard Worker                     br->skipBits(descriptor_length * 8);
633*ec779b8eSAndroid Build Coastguard Worker                 } else if (descTagExt == EXT_DESCRIPTOR_DVB_DTS_HD) {
634*ec779b8eSAndroid Build Coastguard Worker                     // DTS HD extended descriptor which can accommodate core only formats
635*ec779b8eSAndroid Build Coastguard Worker                     // as well as extension only and core + extension combinations.
636*ec779b8eSAndroid Build Coastguard Worker                     info.mTypeExt = EXT_DESCRIPTOR_DVB_DTS_HD;
637*ec779b8eSAndroid Build Coastguard Worker                     br->skipBits(descriptor_length * 8);
638*ec779b8eSAndroid Build Coastguard Worker                 } else if (descTagExt == EXT_DESCRIPTOR_DVB_DTS_UHD) {
639*ec779b8eSAndroid Build Coastguard Worker                     // The DTS-UHD descriptor is used in the PSI PMT to identify streams
640*ec779b8eSAndroid Build Coastguard Worker                     // which carry DTS-UHD audio
641*ec779b8eSAndroid Build Coastguard Worker                     info.mTypeExt = EXT_DESCRIPTOR_DVB_DTS_UHD;
642*ec779b8eSAndroid Build Coastguard Worker                     br->skipBits(descriptor_length * 8);
643*ec779b8eSAndroid Build Coastguard Worker                 } else if (descTagExt == EXT_DESCRIPTOR_DVB_AUDIO_PRESELECTION &&
644*ec779b8eSAndroid Build Coastguard Worker                            descriptor_length >= 1) {
645*ec779b8eSAndroid Build Coastguard Worker                     if (br->numBitsLeft() < 8) {
646*ec779b8eSAndroid Build Coastguard Worker                         ALOGE("Not enough data left in bitreader!");
647*ec779b8eSAndroid Build Coastguard Worker                         return ERROR_MALFORMED;
648*ec779b8eSAndroid Build Coastguard Worker                     }
649*ec779b8eSAndroid Build Coastguard Worker                     // DVB BlueBook A038 Table 110
650*ec779b8eSAndroid Build Coastguard Worker                     unsigned num_preselections = br->getBits(5);
651*ec779b8eSAndroid Build Coastguard Worker                     br->skipBits(3);  // reserved
652*ec779b8eSAndroid Build Coastguard Worker                     for (unsigned i = 0; i < num_preselections; ++i) {
653*ec779b8eSAndroid Build Coastguard Worker                         if (br->numBitsLeft() < 16) {
654*ec779b8eSAndroid Build Coastguard Worker                             ALOGE("Not enough data left in bitreader!");
655*ec779b8eSAndroid Build Coastguard Worker                             return ERROR_MALFORMED;
656*ec779b8eSAndroid Build Coastguard Worker                         }
657*ec779b8eSAndroid Build Coastguard Worker                         AudioPresentationV1 ap;
658*ec779b8eSAndroid Build Coastguard Worker                         ap.mPresentationId = br->getBits(5);  // preselection_id
659*ec779b8eSAndroid Build Coastguard Worker 
660*ec779b8eSAndroid Build Coastguard Worker                         // audio_rendering_indication
661*ec779b8eSAndroid Build Coastguard Worker                         ap.mMasteringIndication = static_cast<MasteringIndication>(br->getBits(3));
662*ec779b8eSAndroid Build Coastguard Worker                         ap.mAudioDescriptionAvailable = (br->getBits(1) == 1);
663*ec779b8eSAndroid Build Coastguard Worker                         ap.mSpokenSubtitlesAvailable = (br->getBits(1) == 1);
664*ec779b8eSAndroid Build Coastguard Worker                         ap.mDialogueEnhancementAvailable = (br->getBits(1) == 1);
665*ec779b8eSAndroid Build Coastguard Worker 
666*ec779b8eSAndroid Build Coastguard Worker                         bool interactivity_enabled = (br->getBits(1) == 1);
667*ec779b8eSAndroid Build Coastguard Worker                         MY_LOGV("      interactivity_enabled = %d", interactivity_enabled);
668*ec779b8eSAndroid Build Coastguard Worker 
669*ec779b8eSAndroid Build Coastguard Worker                         bool language_code_present = (br->getBits(1) == 1);
670*ec779b8eSAndroid Build Coastguard Worker                         bool text_label_present = (br->getBits(1) == 1);
671*ec779b8eSAndroid Build Coastguard Worker 
672*ec779b8eSAndroid Build Coastguard Worker                         bool multi_stream_info_present = (br->getBits(1) == 1);
673*ec779b8eSAndroid Build Coastguard Worker                         bool future_extension = (br->getBits(1) == 1);
674*ec779b8eSAndroid Build Coastguard Worker                         if (language_code_present) {
675*ec779b8eSAndroid Build Coastguard Worker                             if (br->numBitsLeft() < 24) {
676*ec779b8eSAndroid Build Coastguard Worker                                 ALOGE("Not enough data left in bitreader!");
677*ec779b8eSAndroid Build Coastguard Worker                                 return ERROR_MALFORMED;
678*ec779b8eSAndroid Build Coastguard Worker                             }
679*ec779b8eSAndroid Build Coastguard Worker                             char language[4];
680*ec779b8eSAndroid Build Coastguard Worker                             language[0] = br->getBits(8);
681*ec779b8eSAndroid Build Coastguard Worker                             language[1] = br->getBits(8);
682*ec779b8eSAndroid Build Coastguard Worker                             language[2] = br->getBits(8);
683*ec779b8eSAndroid Build Coastguard Worker                             language[3] = 0;
684*ec779b8eSAndroid Build Coastguard Worker                             ap.mLanguage = String8(language);
685*ec779b8eSAndroid Build Coastguard Worker                         }
686*ec779b8eSAndroid Build Coastguard Worker 
687*ec779b8eSAndroid Build Coastguard Worker                         // This maps the presentation id to the message id in the
688*ec779b8eSAndroid Build Coastguard Worker                         // EXT_DESCRIPTOR_DVB_MESSAGE so that we can get the presentation label.
689*ec779b8eSAndroid Build Coastguard Worker                         if (text_label_present) {
690*ec779b8eSAndroid Build Coastguard Worker                             if (br->numBitsLeft() < 8) {
691*ec779b8eSAndroid Build Coastguard Worker                                 ALOGE("Not enough data left in bitreader!");
692*ec779b8eSAndroid Build Coastguard Worker                                 return ERROR_MALFORMED;
693*ec779b8eSAndroid Build Coastguard Worker                             }
694*ec779b8eSAndroid Build Coastguard Worker                             unsigned message_id = br->getBits(8);
695*ec779b8eSAndroid Build Coastguard Worker                             MY_LOGV("      message_id = %u", message_id);
696*ec779b8eSAndroid Build Coastguard Worker                         }
697*ec779b8eSAndroid Build Coastguard Worker 
698*ec779b8eSAndroid Build Coastguard Worker                         if (multi_stream_info_present) {
699*ec779b8eSAndroid Build Coastguard Worker                             if (br->numBitsLeft() < 8) {
700*ec779b8eSAndroid Build Coastguard Worker                                 ALOGE("Not enough data left in bitreader!");
701*ec779b8eSAndroid Build Coastguard Worker                                 return ERROR_MALFORMED;
702*ec779b8eSAndroid Build Coastguard Worker                             }
703*ec779b8eSAndroid Build Coastguard Worker                             unsigned num_aux_components = br->getBits(3);
704*ec779b8eSAndroid Build Coastguard Worker                             br->skipBits(5);  // reserved
705*ec779b8eSAndroid Build Coastguard Worker                             if (br->numBitsLeft() < (num_aux_components * 8)) {
706*ec779b8eSAndroid Build Coastguard Worker                                 ALOGE("Not enough data left in bitreader!");
707*ec779b8eSAndroid Build Coastguard Worker                                 return ERROR_MALFORMED;
708*ec779b8eSAndroid Build Coastguard Worker                             }
709*ec779b8eSAndroid Build Coastguard Worker                             br->skipBits(num_aux_components * 8);  // component_tag
710*ec779b8eSAndroid Build Coastguard Worker                         }
711*ec779b8eSAndroid Build Coastguard Worker                         if (future_extension) {
712*ec779b8eSAndroid Build Coastguard Worker                             if (br->numBitsLeft() < 8) {
713*ec779b8eSAndroid Build Coastguard Worker                                 return ERROR_MALFORMED;
714*ec779b8eSAndroid Build Coastguard Worker                             }
715*ec779b8eSAndroid Build Coastguard Worker                             br->skipBits(3);  // reserved
716*ec779b8eSAndroid Build Coastguard Worker                             unsigned future_extension_length = br->getBits(5);
717*ec779b8eSAndroid Build Coastguard Worker                             if (br->numBitsLeft() < (future_extension_length * 8)) {
718*ec779b8eSAndroid Build Coastguard Worker                                 ALOGE("Not enough data left in bitreader!");
719*ec779b8eSAndroid Build Coastguard Worker                                 return ERROR_MALFORMED;
720*ec779b8eSAndroid Build Coastguard Worker                             }
721*ec779b8eSAndroid Build Coastguard Worker                             br->skipBits(future_extension_length * 8);  // future_extension_byte
722*ec779b8eSAndroid Build Coastguard Worker                         }
723*ec779b8eSAndroid Build Coastguard Worker                         info.mAudioPresentations.push_back(std::move(ap));
724*ec779b8eSAndroid Build Coastguard Worker                     }
725*ec779b8eSAndroid Build Coastguard Worker                 } else {
726*ec779b8eSAndroid Build Coastguard Worker                     if (!br->skipBits(descriptor_length * 8)) {
727*ec779b8eSAndroid Build Coastguard Worker                         ALOGE("Not enough data left in bitreader!");
728*ec779b8eSAndroid Build Coastguard Worker                         return ERROR_MALFORMED;
729*ec779b8eSAndroid Build Coastguard Worker                     }
730*ec779b8eSAndroid Build Coastguard Worker                 }
731*ec779b8eSAndroid Build Coastguard Worker             } else {
732*ec779b8eSAndroid Build Coastguard Worker                 ES_info_length -= descriptor_length;
733*ec779b8eSAndroid Build Coastguard Worker                 if (!br->skipBits(descriptor_length * 8)) {
734*ec779b8eSAndroid Build Coastguard Worker                     ALOGE("Not enough data left in bitreader!");
735*ec779b8eSAndroid Build Coastguard Worker                     return ERROR_MALFORMED;
736*ec779b8eSAndroid Build Coastguard Worker                 }
737*ec779b8eSAndroid Build Coastguard Worker             }
738*ec779b8eSAndroid Build Coastguard Worker         }
739*ec779b8eSAndroid Build Coastguard Worker         if (hasStreamCA && !mParser->mCasManager->addStream(
740*ec779b8eSAndroid Build Coastguard Worker                 mProgramNumber, info.mPID, streamCA)) {
741*ec779b8eSAndroid Build Coastguard Worker             return ERROR_MALFORMED;
742*ec779b8eSAndroid Build Coastguard Worker         }
743*ec779b8eSAndroid Build Coastguard Worker         if (hasProgramCA) {
744*ec779b8eSAndroid Build Coastguard Worker             info.mCADescriptor = programCA;
745*ec779b8eSAndroid Build Coastguard Worker         } else if (hasStreamCA) {
746*ec779b8eSAndroid Build Coastguard Worker             info.mCADescriptor = streamCA;
747*ec779b8eSAndroid Build Coastguard Worker         }
748*ec779b8eSAndroid Build Coastguard Worker 
749*ec779b8eSAndroid Build Coastguard Worker         infos.push(info);
750*ec779b8eSAndroid Build Coastguard Worker     }
751*ec779b8eSAndroid Build Coastguard Worker 
752*ec779b8eSAndroid Build Coastguard Worker     if (infoBytesRemaining != 0) {
753*ec779b8eSAndroid Build Coastguard Worker         ALOGW("Section data remains unconsumed");
754*ec779b8eSAndroid Build Coastguard Worker     }
755*ec779b8eSAndroid Build Coastguard Worker     if (br->numBitsLeft() < 32) {
756*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Not enough data left in bitreader!");
757*ec779b8eSAndroid Build Coastguard Worker         return ERROR_MALFORMED;
758*ec779b8eSAndroid Build Coastguard Worker     }
759*ec779b8eSAndroid Build Coastguard Worker     unsigned crc = br->getBits(32);
760*ec779b8eSAndroid Build Coastguard Worker     if (crc != mPMT_CRC) {
761*ec779b8eSAndroid Build Coastguard Worker         audioPresentationsChanged = true;
762*ec779b8eSAndroid Build Coastguard Worker         mPMT_CRC = crc;
763*ec779b8eSAndroid Build Coastguard Worker     }
764*ec779b8eSAndroid Build Coastguard Worker     MY_LOGV("  CRC = 0x%08x", crc);
765*ec779b8eSAndroid Build Coastguard Worker 
766*ec779b8eSAndroid Build Coastguard Worker     bool PIDsChanged = false;
767*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < infos.size(); ++i) {
768*ec779b8eSAndroid Build Coastguard Worker         StreamInfo &info = infos.editItemAt(i);
769*ec779b8eSAndroid Build Coastguard Worker 
770*ec779b8eSAndroid Build Coastguard Worker         ssize_t index = mStreams.indexOfKey(info.mPID);
771*ec779b8eSAndroid Build Coastguard Worker 
772*ec779b8eSAndroid Build Coastguard Worker         if (index >= 0 && mStreams.editValueAt(index)->type() != info.mType) {
773*ec779b8eSAndroid Build Coastguard Worker             ALOGI("uh oh. stream PIDs have changed.");
774*ec779b8eSAndroid Build Coastguard Worker             PIDsChanged = true;
775*ec779b8eSAndroid Build Coastguard Worker             break;
776*ec779b8eSAndroid Build Coastguard Worker         }
777*ec779b8eSAndroid Build Coastguard Worker     }
778*ec779b8eSAndroid Build Coastguard Worker 
779*ec779b8eSAndroid Build Coastguard Worker     if (PIDsChanged) {
780*ec779b8eSAndroid Build Coastguard Worker #if 0
781*ec779b8eSAndroid Build Coastguard Worker         ALOGI("before:");
782*ec779b8eSAndroid Build Coastguard Worker         for (size_t i = 0; i < mStreams.size(); ++i) {
783*ec779b8eSAndroid Build Coastguard Worker             sp<Stream> stream = mStreams.editValueAt(i);
784*ec779b8eSAndroid Build Coastguard Worker 
785*ec779b8eSAndroid Build Coastguard Worker             ALOGI("PID 0x%08x => type 0x%02x", stream->pid(), stream->type());
786*ec779b8eSAndroid Build Coastguard Worker         }
787*ec779b8eSAndroid Build Coastguard Worker 
788*ec779b8eSAndroid Build Coastguard Worker         ALOGI("after:");
789*ec779b8eSAndroid Build Coastguard Worker         for (size_t i = 0; i < infos.size(); ++i) {
790*ec779b8eSAndroid Build Coastguard Worker             StreamInfo &info = infos.editItemAt(i);
791*ec779b8eSAndroid Build Coastguard Worker 
792*ec779b8eSAndroid Build Coastguard Worker             ALOGI("PID 0x%08x => type 0x%02x", info.mPID, info.mType);
793*ec779b8eSAndroid Build Coastguard Worker         }
794*ec779b8eSAndroid Build Coastguard Worker #endif
795*ec779b8eSAndroid Build Coastguard Worker 
796*ec779b8eSAndroid Build Coastguard Worker         // we can recover if number of streams for each type remain the same
797*ec779b8eSAndroid Build Coastguard Worker         bool success = switchPIDs(infos);
798*ec779b8eSAndroid Build Coastguard Worker 
799*ec779b8eSAndroid Build Coastguard Worker         if (!success) {
800*ec779b8eSAndroid Build Coastguard Worker             ALOGI("Stream PIDs changed and we cannot recover.");
801*ec779b8eSAndroid Build Coastguard Worker             return ERROR_MALFORMED;
802*ec779b8eSAndroid Build Coastguard Worker         }
803*ec779b8eSAndroid Build Coastguard Worker     }
804*ec779b8eSAndroid Build Coastguard Worker 
805*ec779b8eSAndroid Build Coastguard Worker     bool isAddingScrambledStream = false;
806*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < infos.size(); ++i) {
807*ec779b8eSAndroid Build Coastguard Worker         StreamInfo &info = infos.editItemAt(i);
808*ec779b8eSAndroid Build Coastguard Worker 
809*ec779b8eSAndroid Build Coastguard Worker         if (mParser->mCasManager->isCAPid(info.mPID)) {
810*ec779b8eSAndroid Build Coastguard Worker             // skip CA streams (EMM/ECM)
811*ec779b8eSAndroid Build Coastguard Worker             continue;
812*ec779b8eSAndroid Build Coastguard Worker         }
813*ec779b8eSAndroid Build Coastguard Worker         ssize_t index = mStreams.indexOfKey(info.mPID);
814*ec779b8eSAndroid Build Coastguard Worker 
815*ec779b8eSAndroid Build Coastguard Worker         if (index < 0) {
816*ec779b8eSAndroid Build Coastguard Worker             sp<Stream> stream = new Stream(this, PCR_PID, info);
817*ec779b8eSAndroid Build Coastguard Worker 
818*ec779b8eSAndroid Build Coastguard Worker             if (mSampleAesKeyItem != NULL) {
819*ec779b8eSAndroid Build Coastguard Worker                 stream->signalNewSampleAesKey(mSampleAesKeyItem);
820*ec779b8eSAndroid Build Coastguard Worker             }
821*ec779b8eSAndroid Build Coastguard Worker 
822*ec779b8eSAndroid Build Coastguard Worker             isAddingScrambledStream |= info.mCADescriptor.mSystemID >= 0;
823*ec779b8eSAndroid Build Coastguard Worker             mStreams.add(info.mPID, stream);
824*ec779b8eSAndroid Build Coastguard Worker         }
825*ec779b8eSAndroid Build Coastguard Worker         else if (index >= 0 && mStreams.editValueAt(index)->isAudio()
826*ec779b8eSAndroid Build Coastguard Worker                  && audioPresentationsChanged) {
827*ec779b8eSAndroid Build Coastguard Worker             mStreams.editValueAt(index)->setAudioPresentations(info.mAudioPresentations);
828*ec779b8eSAndroid Build Coastguard Worker         }
829*ec779b8eSAndroid Build Coastguard Worker     }
830*ec779b8eSAndroid Build Coastguard Worker 
831*ec779b8eSAndroid Build Coastguard Worker     if (isAddingScrambledStream) {
832*ec779b8eSAndroid Build Coastguard Worker         ALOGI("Receiving scrambled streams without descrambler!");
833*ec779b8eSAndroid Build Coastguard Worker         return ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED;
834*ec779b8eSAndroid Build Coastguard Worker     }
835*ec779b8eSAndroid Build Coastguard Worker     return OK;
836*ec779b8eSAndroid Build Coastguard Worker }
837*ec779b8eSAndroid Build Coastguard Worker 
recoverPTS(uint64_t PTS_33bit)838*ec779b8eSAndroid Build Coastguard Worker int64_t ATSParser::Program::recoverPTS(uint64_t PTS_33bit) {
839*ec779b8eSAndroid Build Coastguard Worker     // We only have the lower 33-bit of the PTS. It could overflow within a
840*ec779b8eSAndroid Build Coastguard Worker     // reasonable amount of time. To handle the wrap-around, use fancy math
841*ec779b8eSAndroid Build Coastguard Worker     // to get an extended PTS that is within [-0xffffffff, 0xffffffff]
842*ec779b8eSAndroid Build Coastguard Worker     // of the latest recovered PTS.
843*ec779b8eSAndroid Build Coastguard Worker     if (mLastRecoveredPTS < 0LL) {
844*ec779b8eSAndroid Build Coastguard Worker         // Use the original 33bit number for 1st frame, the reason is that
845*ec779b8eSAndroid Build Coastguard Worker         // if 1st frame wraps to negative that's far away from 0, we could
846*ec779b8eSAndroid Build Coastguard Worker         // never start. Only start wrapping around from 2nd frame.
847*ec779b8eSAndroid Build Coastguard Worker         mLastRecoveredPTS = static_cast<int64_t>(PTS_33bit);
848*ec779b8eSAndroid Build Coastguard Worker     } else {
849*ec779b8eSAndroid Build Coastguard Worker         mLastRecoveredPTS = static_cast<int64_t>(
850*ec779b8eSAndroid Build Coastguard Worker                 ((mLastRecoveredPTS - static_cast<int64_t>(PTS_33bit) + 0x100000000LL)
851*ec779b8eSAndroid Build Coastguard Worker                 & 0xfffffffe00000000ull) | PTS_33bit);
852*ec779b8eSAndroid Build Coastguard Worker         // We start from 0, but recovered PTS could be slightly below 0.
853*ec779b8eSAndroid Build Coastguard Worker         // Clamp it to 0 as rest of the pipeline doesn't take negative pts.
854*ec779b8eSAndroid Build Coastguard Worker         // (eg. video is read first and starts at 0, but audio starts at 0xfffffff0)
855*ec779b8eSAndroid Build Coastguard Worker         if (mLastRecoveredPTS < 0LL) {
856*ec779b8eSAndroid Build Coastguard Worker             ALOGI("Clamping negative recovered PTS (%" PRId64 ") to 0", mLastRecoveredPTS);
857*ec779b8eSAndroid Build Coastguard Worker             mLastRecoveredPTS = 0LL;
858*ec779b8eSAndroid Build Coastguard Worker         }
859*ec779b8eSAndroid Build Coastguard Worker     }
860*ec779b8eSAndroid Build Coastguard Worker 
861*ec779b8eSAndroid Build Coastguard Worker     return mLastRecoveredPTS;
862*ec779b8eSAndroid Build Coastguard Worker }
863*ec779b8eSAndroid Build Coastguard Worker 
getSource(SourceType type)864*ec779b8eSAndroid Build Coastguard Worker sp<AnotherPacketSource> ATSParser::Program::getSource(SourceType type) {
865*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < mStreams.size(); ++i) {
866*ec779b8eSAndroid Build Coastguard Worker         sp<AnotherPacketSource> source = mStreams.editValueAt(i)->getSource(type);
867*ec779b8eSAndroid Build Coastguard Worker         if (source != NULL) {
868*ec779b8eSAndroid Build Coastguard Worker             return source;
869*ec779b8eSAndroid Build Coastguard Worker         }
870*ec779b8eSAndroid Build Coastguard Worker     }
871*ec779b8eSAndroid Build Coastguard Worker 
872*ec779b8eSAndroid Build Coastguard Worker     return NULL;
873*ec779b8eSAndroid Build Coastguard Worker }
874*ec779b8eSAndroid Build Coastguard Worker 
hasSource(SourceType type) const875*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::Program::hasSource(SourceType type) const {
876*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < mStreams.size(); ++i) {
877*ec779b8eSAndroid Build Coastguard Worker         const sp<Stream> &stream = mStreams.valueAt(i);
878*ec779b8eSAndroid Build Coastguard Worker         if (type == AUDIO && stream->isAudio()) {
879*ec779b8eSAndroid Build Coastguard Worker             return true;
880*ec779b8eSAndroid Build Coastguard Worker         } else if (type == VIDEO && stream->isVideo()) {
881*ec779b8eSAndroid Build Coastguard Worker             return true;
882*ec779b8eSAndroid Build Coastguard Worker         } else if (type == META && stream->isMeta()) {
883*ec779b8eSAndroid Build Coastguard Worker             return true;
884*ec779b8eSAndroid Build Coastguard Worker         }
885*ec779b8eSAndroid Build Coastguard Worker     }
886*ec779b8eSAndroid Build Coastguard Worker 
887*ec779b8eSAndroid Build Coastguard Worker     return false;
888*ec779b8eSAndroid Build Coastguard Worker }
889*ec779b8eSAndroid Build Coastguard Worker 
convertPTSToTimestamp(uint64_t PTS)890*ec779b8eSAndroid Build Coastguard Worker int64_t ATSParser::Program::convertPTSToTimestamp(uint64_t PTS) {
891*ec779b8eSAndroid Build Coastguard Worker     PTS = recoverPTS(PTS);
892*ec779b8eSAndroid Build Coastguard Worker 
893*ec779b8eSAndroid Build Coastguard Worker     if (!(mParser->mFlags & TS_TIMESTAMPS_ARE_ABSOLUTE)) {
894*ec779b8eSAndroid Build Coastguard Worker         if (!mFirstPTSValid) {
895*ec779b8eSAndroid Build Coastguard Worker             mFirstPTSValid = true;
896*ec779b8eSAndroid Build Coastguard Worker             mFirstPTS = PTS;
897*ec779b8eSAndroid Build Coastguard Worker             PTS = 0;
898*ec779b8eSAndroid Build Coastguard Worker         } else if (PTS < mFirstPTS) {
899*ec779b8eSAndroid Build Coastguard Worker             PTS = 0;
900*ec779b8eSAndroid Build Coastguard Worker         } else {
901*ec779b8eSAndroid Build Coastguard Worker             PTS -= mFirstPTS;
902*ec779b8eSAndroid Build Coastguard Worker         }
903*ec779b8eSAndroid Build Coastguard Worker     }
904*ec779b8eSAndroid Build Coastguard Worker 
905*ec779b8eSAndroid Build Coastguard Worker     int64_t timeUs = (PTS * 100) / 9;
906*ec779b8eSAndroid Build Coastguard Worker 
907*ec779b8eSAndroid Build Coastguard Worker     if (mParser->mAbsoluteTimeAnchorUs >= 0LL) {
908*ec779b8eSAndroid Build Coastguard Worker         timeUs += mParser->mAbsoluteTimeAnchorUs;
909*ec779b8eSAndroid Build Coastguard Worker     }
910*ec779b8eSAndroid Build Coastguard Worker 
911*ec779b8eSAndroid Build Coastguard Worker     if (mParser->mTimeOffsetValid) {
912*ec779b8eSAndroid Build Coastguard Worker         timeUs += mParser->mTimeOffsetUs;
913*ec779b8eSAndroid Build Coastguard Worker     }
914*ec779b8eSAndroid Build Coastguard Worker 
915*ec779b8eSAndroid Build Coastguard Worker     return timeUs;
916*ec779b8eSAndroid Build Coastguard Worker }
917*ec779b8eSAndroid Build Coastguard Worker 
updateCasSessions()918*ec779b8eSAndroid Build Coastguard Worker void ATSParser::Program::updateCasSessions() {
919*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < mStreams.size(); ++i) {
920*ec779b8eSAndroid Build Coastguard Worker         sp<Stream> &stream = mStreams.editValueAt(i);
921*ec779b8eSAndroid Build Coastguard Worker         sp<IDescrambler> descrambler;
922*ec779b8eSAndroid Build Coastguard Worker         std::vector<uint8_t> sessionId;
923*ec779b8eSAndroid Build Coastguard Worker         int32_t systemId;
924*ec779b8eSAndroid Build Coastguard Worker         if (mParser->mCasManager->getCasInfo(mProgramNumber, stream->pid(),
925*ec779b8eSAndroid Build Coastguard Worker                 &systemId, &descrambler, &sessionId)) {
926*ec779b8eSAndroid Build Coastguard Worker             stream->setCasInfo(systemId, descrambler, sessionId);
927*ec779b8eSAndroid Build Coastguard Worker         }
928*ec779b8eSAndroid Build Coastguard Worker     }
929*ec779b8eSAndroid Build Coastguard Worker }
930*ec779b8eSAndroid Build Coastguard Worker 
931*ec779b8eSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
932*ec779b8eSAndroid Build Coastguard Worker static const size_t kInitialStreamBufferSize = 192 * 1024;
933*ec779b8eSAndroid Build Coastguard Worker 
Stream(Program * program,unsigned PCR_PID,const StreamInfo & info)934*ec779b8eSAndroid Build Coastguard Worker ATSParser::Stream::Stream(
935*ec779b8eSAndroid Build Coastguard Worker         Program *program, unsigned PCR_PID, const StreamInfo &info)
936*ec779b8eSAndroid Build Coastguard Worker     : mProgram(program),
937*ec779b8eSAndroid Build Coastguard Worker       mElementaryPID(info.mPID),
938*ec779b8eSAndroid Build Coastguard Worker       mStreamType(info.mType),
939*ec779b8eSAndroid Build Coastguard Worker       mStreamTypeExt(info.mTypeExt),
940*ec779b8eSAndroid Build Coastguard Worker       mPCR_PID(PCR_PID),
941*ec779b8eSAndroid Build Coastguard Worker       mExpectedContinuityCounter(-1),
942*ec779b8eSAndroid Build Coastguard Worker       mPayloadStarted(false),
943*ec779b8eSAndroid Build Coastguard Worker       mEOSReached(false),
944*ec779b8eSAndroid Build Coastguard Worker       mPrevPTS(0),
945*ec779b8eSAndroid Build Coastguard Worker       mQueue(NULL),
946*ec779b8eSAndroid Build Coastguard Worker       mScrambled(info.mCADescriptor.mSystemID >= 0),
947*ec779b8eSAndroid Build Coastguard Worker       mAudioPresentations(info.mAudioPresentations) {
948*ec779b8eSAndroid Build Coastguard Worker     mSampleEncrypted =
949*ec779b8eSAndroid Build Coastguard Worker             mStreamType == STREAMTYPE_H264_ENCRYPTED ||
950*ec779b8eSAndroid Build Coastguard Worker             mStreamType == STREAMTYPE_AAC_ENCRYPTED  ||
951*ec779b8eSAndroid Build Coastguard Worker             mStreamType == STREAMTYPE_AC3_ENCRYPTED;
952*ec779b8eSAndroid Build Coastguard Worker 
953*ec779b8eSAndroid Build Coastguard Worker     ALOGV("new stream PID 0x%02x, type 0x%02x, scrambled %d, SampleEncrypted: %d",
954*ec779b8eSAndroid Build Coastguard Worker             info.mPID, info.mType, mScrambled, mSampleEncrypted);
955*ec779b8eSAndroid Build Coastguard Worker 
956*ec779b8eSAndroid Build Coastguard Worker     uint32_t flags = 0;
957*ec779b8eSAndroid Build Coastguard Worker     if (((isVideo() || isAudio()) && mScrambled)) {
958*ec779b8eSAndroid Build Coastguard Worker         flags = ElementaryStreamQueue::kFlag_ScrambledData;
959*ec779b8eSAndroid Build Coastguard Worker     } else if (mSampleEncrypted) {
960*ec779b8eSAndroid Build Coastguard Worker         flags = ElementaryStreamQueue::kFlag_SampleEncryptedData;
961*ec779b8eSAndroid Build Coastguard Worker     }
962*ec779b8eSAndroid Build Coastguard Worker 
963*ec779b8eSAndroid Build Coastguard Worker     ElementaryStreamQueue::Mode mode = ElementaryStreamQueue::INVALID;
964*ec779b8eSAndroid Build Coastguard Worker 
965*ec779b8eSAndroid Build Coastguard Worker     switch (mStreamType) {
966*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_H264:
967*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_H264_ENCRYPTED:
968*ec779b8eSAndroid Build Coastguard Worker             mode = ElementaryStreamQueue::H264;
969*ec779b8eSAndroid Build Coastguard Worker             flags |= (mProgram->parserFlags() & ALIGNED_VIDEO_DATA) ?
970*ec779b8eSAndroid Build Coastguard Worker                     ElementaryStreamQueue::kFlag_AlignedData : 0;
971*ec779b8eSAndroid Build Coastguard Worker             break;
972*ec779b8eSAndroid Build Coastguard Worker 
973*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_MPEG2_AUDIO_ADTS:
974*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_AAC_ENCRYPTED:
975*ec779b8eSAndroid Build Coastguard Worker             mode = ElementaryStreamQueue::AAC;
976*ec779b8eSAndroid Build Coastguard Worker             break;
977*ec779b8eSAndroid Build Coastguard Worker 
978*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_MPEG1_AUDIO:
979*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_MPEG2_AUDIO:
980*ec779b8eSAndroid Build Coastguard Worker             mode = ElementaryStreamQueue::MPEG_AUDIO;
981*ec779b8eSAndroid Build Coastguard Worker             break;
982*ec779b8eSAndroid Build Coastguard Worker 
983*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_MPEG1_VIDEO:
984*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_MPEG2_VIDEO:
985*ec779b8eSAndroid Build Coastguard Worker             mode = ElementaryStreamQueue::MPEG_VIDEO;
986*ec779b8eSAndroid Build Coastguard Worker             break;
987*ec779b8eSAndroid Build Coastguard Worker 
988*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_MPEG4_VIDEO:
989*ec779b8eSAndroid Build Coastguard Worker             mode = ElementaryStreamQueue::MPEG4_VIDEO;
990*ec779b8eSAndroid Build Coastguard Worker             break;
991*ec779b8eSAndroid Build Coastguard Worker 
992*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_LPCM_AC3:
993*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_AC3:
994*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_AC3_ENCRYPTED:
995*ec779b8eSAndroid Build Coastguard Worker             mode = ElementaryStreamQueue::AC3;
996*ec779b8eSAndroid Build Coastguard Worker             break;
997*ec779b8eSAndroid Build Coastguard Worker 
998*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_EAC3:
999*ec779b8eSAndroid Build Coastguard Worker             mode = ElementaryStreamQueue::EAC3;
1000*ec779b8eSAndroid Build Coastguard Worker             break;
1001*ec779b8eSAndroid Build Coastguard Worker 
1002*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_DTS:
1003*ec779b8eSAndroid Build Coastguard Worker             mode = ElementaryStreamQueue::DTS;
1004*ec779b8eSAndroid Build Coastguard Worker             break;
1005*ec779b8eSAndroid Build Coastguard Worker 
1006*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_PES_PRIVATE_DATA:
1007*ec779b8eSAndroid Build Coastguard Worker             if (mStreamTypeExt == EXT_DESCRIPTOR_DVB_AC4) {
1008*ec779b8eSAndroid Build Coastguard Worker                 mode = ElementaryStreamQueue::AC4;
1009*ec779b8eSAndroid Build Coastguard Worker             } else if (mStreamTypeExt == EXT_DESCRIPTOR_DVB_DTS_HD) {
1010*ec779b8eSAndroid Build Coastguard Worker                 mode = ElementaryStreamQueue::DTS_HD;
1011*ec779b8eSAndroid Build Coastguard Worker             } else if (mStreamTypeExt == EXT_DESCRIPTOR_DVB_DTS_UHD) {
1012*ec779b8eSAndroid Build Coastguard Worker                 mode = ElementaryStreamQueue::DTS_UHD;
1013*ec779b8eSAndroid Build Coastguard Worker             }
1014*ec779b8eSAndroid Build Coastguard Worker             break;
1015*ec779b8eSAndroid Build Coastguard Worker 
1016*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_METADATA:
1017*ec779b8eSAndroid Build Coastguard Worker             mode = ElementaryStreamQueue::METADATA;
1018*ec779b8eSAndroid Build Coastguard Worker             break;
1019*ec779b8eSAndroid Build Coastguard Worker 
1020*ec779b8eSAndroid Build Coastguard Worker         default:
1021*ec779b8eSAndroid Build Coastguard Worker             ALOGE("stream PID 0x%02x has invalid stream type 0x%02x",
1022*ec779b8eSAndroid Build Coastguard Worker                     info.mPID, info.mType);
1023*ec779b8eSAndroid Build Coastguard Worker             return;
1024*ec779b8eSAndroid Build Coastguard Worker     }
1025*ec779b8eSAndroid Build Coastguard Worker 
1026*ec779b8eSAndroid Build Coastguard Worker     mQueue = new ElementaryStreamQueue(mode, flags);
1027*ec779b8eSAndroid Build Coastguard Worker 
1028*ec779b8eSAndroid Build Coastguard Worker     if (mQueue != NULL) {
1029*ec779b8eSAndroid Build Coastguard Worker         if (mSampleAesKeyItem != NULL) {
1030*ec779b8eSAndroid Build Coastguard Worker             mQueue->signalNewSampleAesKey(mSampleAesKeyItem);
1031*ec779b8eSAndroid Build Coastguard Worker         }
1032*ec779b8eSAndroid Build Coastguard Worker 
1033*ec779b8eSAndroid Build Coastguard Worker         ensureBufferCapacity(kInitialStreamBufferSize);
1034*ec779b8eSAndroid Build Coastguard Worker 
1035*ec779b8eSAndroid Build Coastguard Worker         if (mScrambled && (isAudio() || isVideo())) {
1036*ec779b8eSAndroid Build Coastguard Worker             // Set initial format to scrambled
1037*ec779b8eSAndroid Build Coastguard Worker             sp<MetaData> meta = new MetaData();
1038*ec779b8eSAndroid Build Coastguard Worker             meta->setCString(kKeyMIMEType,
1039*ec779b8eSAndroid Build Coastguard Worker                     isAudio() ? MEDIA_MIMETYPE_AUDIO_SCRAMBLED
1040*ec779b8eSAndroid Build Coastguard Worker                               : MEDIA_MIMETYPE_VIDEO_SCRAMBLED);
1041*ec779b8eSAndroid Build Coastguard Worker             // for MediaExtractor.CasInfo
1042*ec779b8eSAndroid Build Coastguard Worker             const CADescriptor &descriptor = info.mCADescriptor;
1043*ec779b8eSAndroid Build Coastguard Worker             meta->setInt32(kKeyCASystemID, descriptor.mSystemID);
1044*ec779b8eSAndroid Build Coastguard Worker 
1045*ec779b8eSAndroid Build Coastguard Worker             meta->setData(kKeyCAPrivateData, 0,
1046*ec779b8eSAndroid Build Coastguard Worker                     descriptor.mPrivateData.data(),
1047*ec779b8eSAndroid Build Coastguard Worker                     descriptor.mPrivateData.size());
1048*ec779b8eSAndroid Build Coastguard Worker 
1049*ec779b8eSAndroid Build Coastguard Worker             mSource = new AnotherPacketSource(meta);
1050*ec779b8eSAndroid Build Coastguard Worker         }
1051*ec779b8eSAndroid Build Coastguard Worker     }
1052*ec779b8eSAndroid Build Coastguard Worker }
1053*ec779b8eSAndroid Build Coastguard Worker 
~Stream()1054*ec779b8eSAndroid Build Coastguard Worker ATSParser::Stream::~Stream() {
1055*ec779b8eSAndroid Build Coastguard Worker     delete mQueue;
1056*ec779b8eSAndroid Build Coastguard Worker     mQueue = NULL;
1057*ec779b8eSAndroid Build Coastguard Worker }
1058*ec779b8eSAndroid Build Coastguard Worker 
ensureBufferCapacity(size_t neededSize)1059*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::Stream::ensureBufferCapacity(size_t neededSize) {
1060*ec779b8eSAndroid Build Coastguard Worker     if (mBuffer != NULL && mBuffer->capacity() >= neededSize) {
1061*ec779b8eSAndroid Build Coastguard Worker         return true;
1062*ec779b8eSAndroid Build Coastguard Worker     }
1063*ec779b8eSAndroid Build Coastguard Worker 
1064*ec779b8eSAndroid Build Coastguard Worker     ALOGV("ensureBufferCapacity: current size %zu, new size %zu, scrambled %d",
1065*ec779b8eSAndroid Build Coastguard Worker             mBuffer == NULL ? 0 : mBuffer->capacity(), neededSize, mScrambled);
1066*ec779b8eSAndroid Build Coastguard Worker 
1067*ec779b8eSAndroid Build Coastguard Worker     sp<ABuffer> newBuffer, newScrambledBuffer;
1068*ec779b8eSAndroid Build Coastguard Worker     sp<TMemory> newMem;
1069*ec779b8eSAndroid Build Coastguard Worker     if (mScrambled) {
1070*ec779b8eSAndroid Build Coastguard Worker         int fd = ashmem_create_region("mediaATS", neededSize);
1071*ec779b8eSAndroid Build Coastguard Worker         if (fd < 0) {
1072*ec779b8eSAndroid Build Coastguard Worker              ALOGE("[stream %d] create_ashmem_region failed for size %zu. FD returned: %d",
1073*ec779b8eSAndroid Build Coastguard Worker                     mElementaryPID, neededSize, fd);
1074*ec779b8eSAndroid Build Coastguard Worker             return false;
1075*ec779b8eSAndroid Build Coastguard Worker         }
1076*ec779b8eSAndroid Build Coastguard Worker 
1077*ec779b8eSAndroid Build Coastguard Worker         native_handle_t* handle = native_handle_create(1 /*numFds*/, 0/*numInts*/);
1078*ec779b8eSAndroid Build Coastguard Worker         if (handle == nullptr) {
1079*ec779b8eSAndroid Build Coastguard Worker             ALOGE("[stream %d] failed to create a native_handle_t", mElementaryPID);
1080*ec779b8eSAndroid Build Coastguard Worker             if (close(fd)) {
1081*ec779b8eSAndroid Build Coastguard Worker                 ALOGE("[stream %d] failed to close ashmem fd. errno: %s", mElementaryPID,
1082*ec779b8eSAndroid Build Coastguard Worker                       strerror(errno));
1083*ec779b8eSAndroid Build Coastguard Worker             }
1084*ec779b8eSAndroid Build Coastguard Worker 
1085*ec779b8eSAndroid Build Coastguard Worker             return false;
1086*ec779b8eSAndroid Build Coastguard Worker         }
1087*ec779b8eSAndroid Build Coastguard Worker 
1088*ec779b8eSAndroid Build Coastguard Worker         handle->data[0] = fd;
1089*ec779b8eSAndroid Build Coastguard Worker         hidl_handle memHandle;
1090*ec779b8eSAndroid Build Coastguard Worker         memHandle.setTo(handle, true /*shouldOwn*/);
1091*ec779b8eSAndroid Build Coastguard Worker         hidl_memory hidlMemToken("ashmem", memHandle, neededSize);
1092*ec779b8eSAndroid Build Coastguard Worker 
1093*ec779b8eSAndroid Build Coastguard Worker         newMem = mapMemory(hidlMemToken);
1094*ec779b8eSAndroid Build Coastguard Worker         if (newMem == nullptr || newMem->getPointer() == nullptr) {
1095*ec779b8eSAndroid Build Coastguard Worker             ALOGE("[stream %d] hidl failed to map memory", mElementaryPID);
1096*ec779b8eSAndroid Build Coastguard Worker             return false;
1097*ec779b8eSAndroid Build Coastguard Worker         }
1098*ec779b8eSAndroid Build Coastguard Worker 
1099*ec779b8eSAndroid Build Coastguard Worker         newScrambledBuffer = new ABuffer(newMem->getPointer(), newMem->getSize());
1100*ec779b8eSAndroid Build Coastguard Worker 
1101*ec779b8eSAndroid Build Coastguard Worker         if (mDescrambledBuffer != NULL) {
1102*ec779b8eSAndroid Build Coastguard Worker             memcpy(newScrambledBuffer->data(),
1103*ec779b8eSAndroid Build Coastguard Worker                     mDescrambledBuffer->data(), mDescrambledBuffer->size());
1104*ec779b8eSAndroid Build Coastguard Worker             newScrambledBuffer->setRange(0, mDescrambledBuffer->size());
1105*ec779b8eSAndroid Build Coastguard Worker         } else {
1106*ec779b8eSAndroid Build Coastguard Worker             newScrambledBuffer->setRange(0, 0);
1107*ec779b8eSAndroid Build Coastguard Worker         }
1108*ec779b8eSAndroid Build Coastguard Worker         mHidlMemory = newMem;
1109*ec779b8eSAndroid Build Coastguard Worker         mDescrambledBuffer = newScrambledBuffer;
1110*ec779b8eSAndroid Build Coastguard Worker 
1111*ec779b8eSAndroid Build Coastguard Worker         mDescramblerSrcBuffer.heapBase = hidlMemToken;
1112*ec779b8eSAndroid Build Coastguard Worker         mDescramblerSrcBuffer.offset = 0ULL;
1113*ec779b8eSAndroid Build Coastguard Worker         mDescramblerSrcBuffer.size =  (uint64_t)neededSize;
1114*ec779b8eSAndroid Build Coastguard Worker 
1115*ec779b8eSAndroid Build Coastguard Worker         ALOGD("[stream %d] created shared buffer for descrambling, size %zu",
1116*ec779b8eSAndroid Build Coastguard Worker                 mElementaryPID, neededSize);
1117*ec779b8eSAndroid Build Coastguard Worker     } else {
1118*ec779b8eSAndroid Build Coastguard Worker         // Align to multiples of 64K.
1119*ec779b8eSAndroid Build Coastguard Worker         neededSize = (neededSize + 65535) & ~65535;
1120*ec779b8eSAndroid Build Coastguard Worker     }
1121*ec779b8eSAndroid Build Coastguard Worker 
1122*ec779b8eSAndroid Build Coastguard Worker     newBuffer = new ABuffer(neededSize);
1123*ec779b8eSAndroid Build Coastguard Worker     if (mBuffer != NULL) {
1124*ec779b8eSAndroid Build Coastguard Worker         memcpy(newBuffer->data(), mBuffer->data(), mBuffer->size());
1125*ec779b8eSAndroid Build Coastguard Worker         newBuffer->setRange(0, mBuffer->size());
1126*ec779b8eSAndroid Build Coastguard Worker     } else {
1127*ec779b8eSAndroid Build Coastguard Worker         newBuffer->setRange(0, 0);
1128*ec779b8eSAndroid Build Coastguard Worker     }
1129*ec779b8eSAndroid Build Coastguard Worker     mBuffer = newBuffer;
1130*ec779b8eSAndroid Build Coastguard Worker     return true;
1131*ec779b8eSAndroid Build Coastguard Worker }
1132*ec779b8eSAndroid Build Coastguard Worker 
parse(unsigned continuity_counter,unsigned payload_unit_start_indicator,unsigned transport_scrambling_control,unsigned random_access_indicator,ABitReader * br,SyncEvent * event)1133*ec779b8eSAndroid Build Coastguard Worker status_t ATSParser::Stream::parse(
1134*ec779b8eSAndroid Build Coastguard Worker         unsigned continuity_counter,
1135*ec779b8eSAndroid Build Coastguard Worker         unsigned payload_unit_start_indicator,
1136*ec779b8eSAndroid Build Coastguard Worker         unsigned transport_scrambling_control,
1137*ec779b8eSAndroid Build Coastguard Worker         unsigned random_access_indicator,
1138*ec779b8eSAndroid Build Coastguard Worker         ABitReader *br, SyncEvent *event) {
1139*ec779b8eSAndroid Build Coastguard Worker     if (mQueue == NULL) {
1140*ec779b8eSAndroid Build Coastguard Worker         return OK;
1141*ec779b8eSAndroid Build Coastguard Worker     }
1142*ec779b8eSAndroid Build Coastguard Worker 
1143*ec779b8eSAndroid Build Coastguard Worker     if (mExpectedContinuityCounter >= 0
1144*ec779b8eSAndroid Build Coastguard Worker             && (unsigned)mExpectedContinuityCounter != continuity_counter) {
1145*ec779b8eSAndroid Build Coastguard Worker         ALOGI("discontinuity on stream pid 0x%04x", mElementaryPID);
1146*ec779b8eSAndroid Build Coastguard Worker 
1147*ec779b8eSAndroid Build Coastguard Worker         mPayloadStarted = false;
1148*ec779b8eSAndroid Build Coastguard Worker         mPesStartOffsets.clear();
1149*ec779b8eSAndroid Build Coastguard Worker         mBuffer->setRange(0, 0);
1150*ec779b8eSAndroid Build Coastguard Worker         mSubSamples.clear();
1151*ec779b8eSAndroid Build Coastguard Worker         mExpectedContinuityCounter = -1;
1152*ec779b8eSAndroid Build Coastguard Worker 
1153*ec779b8eSAndroid Build Coastguard Worker #if 0
1154*ec779b8eSAndroid Build Coastguard Worker         // Uncomment this if you'd rather see no corruption whatsoever on
1155*ec779b8eSAndroid Build Coastguard Worker         // screen and suspend updates until we come across another IDR frame.
1156*ec779b8eSAndroid Build Coastguard Worker 
1157*ec779b8eSAndroid Build Coastguard Worker         if (mStreamType == STREAMTYPE_H264) {
1158*ec779b8eSAndroid Build Coastguard Worker             ALOGI("clearing video queue");
1159*ec779b8eSAndroid Build Coastguard Worker             mQueue->clear(true /* clearFormat */);
1160*ec779b8eSAndroid Build Coastguard Worker         }
1161*ec779b8eSAndroid Build Coastguard Worker #endif
1162*ec779b8eSAndroid Build Coastguard Worker 
1163*ec779b8eSAndroid Build Coastguard Worker         if (!payload_unit_start_indicator) {
1164*ec779b8eSAndroid Build Coastguard Worker             return OK;
1165*ec779b8eSAndroid Build Coastguard Worker         }
1166*ec779b8eSAndroid Build Coastguard Worker     }
1167*ec779b8eSAndroid Build Coastguard Worker 
1168*ec779b8eSAndroid Build Coastguard Worker     mExpectedContinuityCounter = (continuity_counter + 1) & 0x0f;
1169*ec779b8eSAndroid Build Coastguard Worker 
1170*ec779b8eSAndroid Build Coastguard Worker     if (payload_unit_start_indicator) {
1171*ec779b8eSAndroid Build Coastguard Worker         off64_t offset = (event != NULL) ? event->getOffset() : 0;
1172*ec779b8eSAndroid Build Coastguard Worker         if (mPayloadStarted) {
1173*ec779b8eSAndroid Build Coastguard Worker             // Otherwise we run the danger of receiving the trailing bytes
1174*ec779b8eSAndroid Build Coastguard Worker             // of a PES packet that we never saw the start of and assuming
1175*ec779b8eSAndroid Build Coastguard Worker             // we have a a complete PES packet.
1176*ec779b8eSAndroid Build Coastguard Worker 
1177*ec779b8eSAndroid Build Coastguard Worker             status_t err = flush(event);
1178*ec779b8eSAndroid Build Coastguard Worker 
1179*ec779b8eSAndroid Build Coastguard Worker             if (err != OK) {
1180*ec779b8eSAndroid Build Coastguard Worker                 ALOGW("Error (%08x) happened while flushing; we simply discard "
1181*ec779b8eSAndroid Build Coastguard Worker                       "the PES packet and continue.", err);
1182*ec779b8eSAndroid Build Coastguard Worker             }
1183*ec779b8eSAndroid Build Coastguard Worker         }
1184*ec779b8eSAndroid Build Coastguard Worker 
1185*ec779b8eSAndroid Build Coastguard Worker         mPayloadStarted = true;
1186*ec779b8eSAndroid Build Coastguard Worker         // There should be at most 2 elements in |mPesStartOffsets|.
1187*ec779b8eSAndroid Build Coastguard Worker         while (mPesStartOffsets.size() >= 2) {
1188*ec779b8eSAndroid Build Coastguard Worker             mPesStartOffsets.erase(mPesStartOffsets.begin());
1189*ec779b8eSAndroid Build Coastguard Worker         }
1190*ec779b8eSAndroid Build Coastguard Worker         mPesStartOffsets.push_back(offset);
1191*ec779b8eSAndroid Build Coastguard Worker     }
1192*ec779b8eSAndroid Build Coastguard Worker 
1193*ec779b8eSAndroid Build Coastguard Worker     if (!mPayloadStarted) {
1194*ec779b8eSAndroid Build Coastguard Worker         return OK;
1195*ec779b8eSAndroid Build Coastguard Worker     }
1196*ec779b8eSAndroid Build Coastguard Worker 
1197*ec779b8eSAndroid Build Coastguard Worker     size_t payloadSizeBits = br->numBitsLeft();
1198*ec779b8eSAndroid Build Coastguard Worker     if (payloadSizeBits % 8 != 0u) {
1199*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Wrong value");
1200*ec779b8eSAndroid Build Coastguard Worker         return BAD_VALUE;
1201*ec779b8eSAndroid Build Coastguard Worker     }
1202*ec779b8eSAndroid Build Coastguard Worker 
1203*ec779b8eSAndroid Build Coastguard Worker     size_t neededSize = mBuffer->size() + payloadSizeBits / 8;
1204*ec779b8eSAndroid Build Coastguard Worker     if (!ensureBufferCapacity(neededSize)) {
1205*ec779b8eSAndroid Build Coastguard Worker         return NO_MEMORY;
1206*ec779b8eSAndroid Build Coastguard Worker     }
1207*ec779b8eSAndroid Build Coastguard Worker 
1208*ec779b8eSAndroid Build Coastguard Worker     memcpy(mBuffer->data() + mBuffer->size(), br->data(), payloadSizeBits / 8);
1209*ec779b8eSAndroid Build Coastguard Worker     mBuffer->setRange(0, mBuffer->size() + payloadSizeBits / 8);
1210*ec779b8eSAndroid Build Coastguard Worker 
1211*ec779b8eSAndroid Build Coastguard Worker     if (mScrambled) {
1212*ec779b8eSAndroid Build Coastguard Worker         mSubSamples.push_back({payloadSizeBits / 8,
1213*ec779b8eSAndroid Build Coastguard Worker                  transport_scrambling_control, random_access_indicator});
1214*ec779b8eSAndroid Build Coastguard Worker     }
1215*ec779b8eSAndroid Build Coastguard Worker 
1216*ec779b8eSAndroid Build Coastguard Worker     return OK;
1217*ec779b8eSAndroid Build Coastguard Worker }
1218*ec779b8eSAndroid Build Coastguard Worker 
isVideo() const1219*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::Stream::isVideo() const {
1220*ec779b8eSAndroid Build Coastguard Worker     switch (mStreamType) {
1221*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_H264:
1222*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_H264_ENCRYPTED:
1223*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_MPEG1_VIDEO:
1224*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_MPEG2_VIDEO:
1225*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_MPEG4_VIDEO:
1226*ec779b8eSAndroid Build Coastguard Worker             return true;
1227*ec779b8eSAndroid Build Coastguard Worker 
1228*ec779b8eSAndroid Build Coastguard Worker         default:
1229*ec779b8eSAndroid Build Coastguard Worker             return false;
1230*ec779b8eSAndroid Build Coastguard Worker     }
1231*ec779b8eSAndroid Build Coastguard Worker }
1232*ec779b8eSAndroid Build Coastguard Worker 
isAudio() const1233*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::Stream::isAudio() const {
1234*ec779b8eSAndroid Build Coastguard Worker     switch (mStreamType) {
1235*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_MPEG1_AUDIO:
1236*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_MPEG2_AUDIO:
1237*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_MPEG2_AUDIO_ADTS:
1238*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_LPCM_AC3:
1239*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_AC3:
1240*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_EAC3:
1241*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_AAC_ENCRYPTED:
1242*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_AC3_ENCRYPTED:
1243*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_DTS:
1244*ec779b8eSAndroid Build Coastguard Worker             return true;
1245*ec779b8eSAndroid Build Coastguard Worker         case STREAMTYPE_PES_PRIVATE_DATA:
1246*ec779b8eSAndroid Build Coastguard Worker             return (mStreamTypeExt == EXT_DESCRIPTOR_DVB_AC4
1247*ec779b8eSAndroid Build Coastguard Worker                     || mStreamTypeExt == EXT_DESCRIPTOR_DVB_DTS_HD
1248*ec779b8eSAndroid Build Coastguard Worker                     || mStreamTypeExt == EXT_DESCRIPTOR_DVB_DTS_UHD);
1249*ec779b8eSAndroid Build Coastguard Worker 
1250*ec779b8eSAndroid Build Coastguard Worker         default:
1251*ec779b8eSAndroid Build Coastguard Worker             return false;
1252*ec779b8eSAndroid Build Coastguard Worker     }
1253*ec779b8eSAndroid Build Coastguard Worker }
1254*ec779b8eSAndroid Build Coastguard Worker 
isMeta() const1255*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::Stream::isMeta() const {
1256*ec779b8eSAndroid Build Coastguard Worker     if (mStreamType == STREAMTYPE_METADATA) {
1257*ec779b8eSAndroid Build Coastguard Worker         return true;
1258*ec779b8eSAndroid Build Coastguard Worker     }
1259*ec779b8eSAndroid Build Coastguard Worker     return false;
1260*ec779b8eSAndroid Build Coastguard Worker }
1261*ec779b8eSAndroid Build Coastguard Worker 
signalDiscontinuity(DiscontinuityType type,const sp<AMessage> & extra)1262*ec779b8eSAndroid Build Coastguard Worker void ATSParser::Stream::signalDiscontinuity(
1263*ec779b8eSAndroid Build Coastguard Worker         DiscontinuityType type, const sp<AMessage> &extra) {
1264*ec779b8eSAndroid Build Coastguard Worker     mExpectedContinuityCounter = -1;
1265*ec779b8eSAndroid Build Coastguard Worker 
1266*ec779b8eSAndroid Build Coastguard Worker     if (mQueue == NULL) {
1267*ec779b8eSAndroid Build Coastguard Worker         return;
1268*ec779b8eSAndroid Build Coastguard Worker     }
1269*ec779b8eSAndroid Build Coastguard Worker 
1270*ec779b8eSAndroid Build Coastguard Worker     mPayloadStarted = false;
1271*ec779b8eSAndroid Build Coastguard Worker     mPesStartOffsets.clear();
1272*ec779b8eSAndroid Build Coastguard Worker     mEOSReached = false;
1273*ec779b8eSAndroid Build Coastguard Worker     mBuffer->setRange(0, 0);
1274*ec779b8eSAndroid Build Coastguard Worker     mSubSamples.clear();
1275*ec779b8eSAndroid Build Coastguard Worker 
1276*ec779b8eSAndroid Build Coastguard Worker     bool clearFormat = false;
1277*ec779b8eSAndroid Build Coastguard Worker     if (isAudio()) {
1278*ec779b8eSAndroid Build Coastguard Worker         if (type & DISCONTINUITY_AUDIO_FORMAT) {
1279*ec779b8eSAndroid Build Coastguard Worker             clearFormat = true;
1280*ec779b8eSAndroid Build Coastguard Worker         }
1281*ec779b8eSAndroid Build Coastguard Worker     } else {
1282*ec779b8eSAndroid Build Coastguard Worker         if (type & DISCONTINUITY_VIDEO_FORMAT) {
1283*ec779b8eSAndroid Build Coastguard Worker             clearFormat = true;
1284*ec779b8eSAndroid Build Coastguard Worker         }
1285*ec779b8eSAndroid Build Coastguard Worker     }
1286*ec779b8eSAndroid Build Coastguard Worker 
1287*ec779b8eSAndroid Build Coastguard Worker     mQueue->clear(clearFormat);
1288*ec779b8eSAndroid Build Coastguard Worker 
1289*ec779b8eSAndroid Build Coastguard Worker     if (type & DISCONTINUITY_TIME) {
1290*ec779b8eSAndroid Build Coastguard Worker         uint64_t resumeAtPTS;
1291*ec779b8eSAndroid Build Coastguard Worker         if (extra != NULL
1292*ec779b8eSAndroid Build Coastguard Worker                 && extra->findInt64(
1293*ec779b8eSAndroid Build Coastguard Worker                     kATSParserKeyResumeAtPTS,
1294*ec779b8eSAndroid Build Coastguard Worker                     (int64_t *)&resumeAtPTS)) {
1295*ec779b8eSAndroid Build Coastguard Worker             int64_t resumeAtMediaTimeUs =
1296*ec779b8eSAndroid Build Coastguard Worker                 mProgram->convertPTSToTimestamp(resumeAtPTS);
1297*ec779b8eSAndroid Build Coastguard Worker 
1298*ec779b8eSAndroid Build Coastguard Worker             extra->setInt64("resume-at-mediaTimeUs", resumeAtMediaTimeUs);
1299*ec779b8eSAndroid Build Coastguard Worker         }
1300*ec779b8eSAndroid Build Coastguard Worker     }
1301*ec779b8eSAndroid Build Coastguard Worker 
1302*ec779b8eSAndroid Build Coastguard Worker     if (mSource != NULL) {
1303*ec779b8eSAndroid Build Coastguard Worker         sp<MetaData> meta = mSource->getFormat();
1304*ec779b8eSAndroid Build Coastguard Worker         const char* mime;
1305*ec779b8eSAndroid Build Coastguard Worker         if (clearFormat && meta != NULL && meta->findCString(kKeyMIMEType, &mime)
1306*ec779b8eSAndroid Build Coastguard Worker                 && (!strncasecmp(mime, MEDIA_MIMETYPE_AUDIO_SCRAMBLED, 15)
1307*ec779b8eSAndroid Build Coastguard Worker                  || !strncasecmp(mime, MEDIA_MIMETYPE_VIDEO_SCRAMBLED, 15))){
1308*ec779b8eSAndroid Build Coastguard Worker             mSource->clear();
1309*ec779b8eSAndroid Build Coastguard Worker         } else {
1310*ec779b8eSAndroid Build Coastguard Worker             mSource->queueDiscontinuity(type, extra, true);
1311*ec779b8eSAndroid Build Coastguard Worker         }
1312*ec779b8eSAndroid Build Coastguard Worker     }
1313*ec779b8eSAndroid Build Coastguard Worker }
1314*ec779b8eSAndroid Build Coastguard Worker 
signalEOS(status_t finalResult)1315*ec779b8eSAndroid Build Coastguard Worker void ATSParser::Stream::signalEOS(status_t finalResult) {
1316*ec779b8eSAndroid Build Coastguard Worker     if (mSource != NULL) {
1317*ec779b8eSAndroid Build Coastguard Worker         mSource->signalEOS(finalResult);
1318*ec779b8eSAndroid Build Coastguard Worker     }
1319*ec779b8eSAndroid Build Coastguard Worker     mEOSReached = true;
1320*ec779b8eSAndroid Build Coastguard Worker     flush(NULL);
1321*ec779b8eSAndroid Build Coastguard Worker }
1322*ec779b8eSAndroid Build Coastguard Worker 
parsePES(ABitReader * br,SyncEvent * event)1323*ec779b8eSAndroid Build Coastguard Worker status_t ATSParser::Stream::parsePES(ABitReader *br, SyncEvent *event) {
1324*ec779b8eSAndroid Build Coastguard Worker     const uint8_t *basePtr = br->data();
1325*ec779b8eSAndroid Build Coastguard Worker 
1326*ec779b8eSAndroid Build Coastguard Worker     if (br->numBitsLeft() < 48) {
1327*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Not enough data left in bitreader!");
1328*ec779b8eSAndroid Build Coastguard Worker         return ERROR_MALFORMED;
1329*ec779b8eSAndroid Build Coastguard Worker     }
1330*ec779b8eSAndroid Build Coastguard Worker     unsigned packet_startcode_prefix = br->getBits(24);
1331*ec779b8eSAndroid Build Coastguard Worker 
1332*ec779b8eSAndroid Build Coastguard Worker     ALOGV("packet_startcode_prefix = 0x%08x", packet_startcode_prefix);
1333*ec779b8eSAndroid Build Coastguard Worker 
1334*ec779b8eSAndroid Build Coastguard Worker     if (packet_startcode_prefix != 1) {
1335*ec779b8eSAndroid Build Coastguard Worker         ALOGV("Supposedly payload_unit_start=1 unit does not start "
1336*ec779b8eSAndroid Build Coastguard Worker              "with startcode.");
1337*ec779b8eSAndroid Build Coastguard Worker 
1338*ec779b8eSAndroid Build Coastguard Worker         return ERROR_MALFORMED;
1339*ec779b8eSAndroid Build Coastguard Worker     }
1340*ec779b8eSAndroid Build Coastguard Worker 
1341*ec779b8eSAndroid Build Coastguard Worker     unsigned stream_id = br->getBits(8);
1342*ec779b8eSAndroid Build Coastguard Worker     ALOGV("stream_id = 0x%02x", stream_id);
1343*ec779b8eSAndroid Build Coastguard Worker 
1344*ec779b8eSAndroid Build Coastguard Worker     unsigned PES_packet_length = br->getBits(16);
1345*ec779b8eSAndroid Build Coastguard Worker     ALOGV("PES_packet_length = %u", PES_packet_length);
1346*ec779b8eSAndroid Build Coastguard Worker 
1347*ec779b8eSAndroid Build Coastguard Worker     if (stream_id != 0xbc  // program_stream_map
1348*ec779b8eSAndroid Build Coastguard Worker             && stream_id != 0xbe  // padding_stream
1349*ec779b8eSAndroid Build Coastguard Worker             && stream_id != 0xbf  // private_stream_2
1350*ec779b8eSAndroid Build Coastguard Worker             && stream_id != 0xf0  // ECM
1351*ec779b8eSAndroid Build Coastguard Worker             && stream_id != 0xf1  // EMM
1352*ec779b8eSAndroid Build Coastguard Worker             && stream_id != 0xff  // program_stream_directory
1353*ec779b8eSAndroid Build Coastguard Worker             && stream_id != 0xf2  // DSMCC
1354*ec779b8eSAndroid Build Coastguard Worker             && stream_id != 0xf8) {  // H.222.1 type E
1355*ec779b8eSAndroid Build Coastguard Worker         if (br->numBitsLeft() < 2 || br->getBits(2) != 2u) {
1356*ec779b8eSAndroid Build Coastguard Worker             return ERROR_MALFORMED;
1357*ec779b8eSAndroid Build Coastguard Worker         }
1358*ec779b8eSAndroid Build Coastguard Worker 
1359*ec779b8eSAndroid Build Coastguard Worker         if (br->numBitsLeft() < 22) {
1360*ec779b8eSAndroid Build Coastguard Worker             ALOGE("Not enough data left in bitreader!");
1361*ec779b8eSAndroid Build Coastguard Worker             return ERROR_MALFORMED;
1362*ec779b8eSAndroid Build Coastguard Worker         }
1363*ec779b8eSAndroid Build Coastguard Worker         unsigned PES_scrambling_control = br->getBits(2);
1364*ec779b8eSAndroid Build Coastguard Worker         ALOGV("PES_scrambling_control = %u", PES_scrambling_control);
1365*ec779b8eSAndroid Build Coastguard Worker 
1366*ec779b8eSAndroid Build Coastguard Worker         MY_LOGV("PES_priority = %u", br->getBits(1));
1367*ec779b8eSAndroid Build Coastguard Worker         MY_LOGV("data_alignment_indicator = %u", br->getBits(1));
1368*ec779b8eSAndroid Build Coastguard Worker         MY_LOGV("copyright = %u", br->getBits(1));
1369*ec779b8eSAndroid Build Coastguard Worker         MY_LOGV("original_or_copy = %u", br->getBits(1));
1370*ec779b8eSAndroid Build Coastguard Worker 
1371*ec779b8eSAndroid Build Coastguard Worker         unsigned PTS_DTS_flags = br->getBits(2);
1372*ec779b8eSAndroid Build Coastguard Worker         ALOGV("PTS_DTS_flags = %u", PTS_DTS_flags);
1373*ec779b8eSAndroid Build Coastguard Worker 
1374*ec779b8eSAndroid Build Coastguard Worker         unsigned ESCR_flag = br->getBits(1);
1375*ec779b8eSAndroid Build Coastguard Worker         ALOGV("ESCR_flag = %u", ESCR_flag);
1376*ec779b8eSAndroid Build Coastguard Worker 
1377*ec779b8eSAndroid Build Coastguard Worker         unsigned ES_rate_flag = br->getBits(1);
1378*ec779b8eSAndroid Build Coastguard Worker         ALOGV("ES_rate_flag = %u", ES_rate_flag);
1379*ec779b8eSAndroid Build Coastguard Worker 
1380*ec779b8eSAndroid Build Coastguard Worker         unsigned DSM_trick_mode_flag = br->getBits(1);
1381*ec779b8eSAndroid Build Coastguard Worker         ALOGV("DSM_trick_mode_flag = %u", DSM_trick_mode_flag);
1382*ec779b8eSAndroid Build Coastguard Worker 
1383*ec779b8eSAndroid Build Coastguard Worker         unsigned additional_copy_info_flag = br->getBits(1);
1384*ec779b8eSAndroid Build Coastguard Worker         ALOGV("additional_copy_info_flag = %u", additional_copy_info_flag);
1385*ec779b8eSAndroid Build Coastguard Worker 
1386*ec779b8eSAndroid Build Coastguard Worker         MY_LOGV("PES_CRC_flag = %u", br->getBits(1));
1387*ec779b8eSAndroid Build Coastguard Worker         MY_LOGV("PES_extension_flag = %u", br->getBits(1));
1388*ec779b8eSAndroid Build Coastguard Worker 
1389*ec779b8eSAndroid Build Coastguard Worker         unsigned PES_header_data_length = br->getBits(8);
1390*ec779b8eSAndroid Build Coastguard Worker         ALOGV("PES_header_data_length = %u", PES_header_data_length);
1391*ec779b8eSAndroid Build Coastguard Worker 
1392*ec779b8eSAndroid Build Coastguard Worker         unsigned optional_bytes_remaining = PES_header_data_length;
1393*ec779b8eSAndroid Build Coastguard Worker 
1394*ec779b8eSAndroid Build Coastguard Worker         uint64_t PTS = 0, DTS = 0;
1395*ec779b8eSAndroid Build Coastguard Worker 
1396*ec779b8eSAndroid Build Coastguard Worker         if (PTS_DTS_flags == 2 || PTS_DTS_flags == 3) {
1397*ec779b8eSAndroid Build Coastguard Worker             if (optional_bytes_remaining < 5u) {
1398*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
1399*ec779b8eSAndroid Build Coastguard Worker             }
1400*ec779b8eSAndroid Build Coastguard Worker 
1401*ec779b8eSAndroid Build Coastguard Worker             if (br->numBitsLeft() < 7 || br->getBits(4) != PTS_DTS_flags) {
1402*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
1403*ec779b8eSAndroid Build Coastguard Worker             }
1404*ec779b8eSAndroid Build Coastguard Worker             PTS = ((uint64_t)br->getBits(3)) << 30;
1405*ec779b8eSAndroid Build Coastguard Worker             if (br->numBitsLeft() < 16 || br->getBits(1) != 1u) {
1406*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
1407*ec779b8eSAndroid Build Coastguard Worker             }
1408*ec779b8eSAndroid Build Coastguard Worker             PTS |= ((uint64_t)br->getBits(15)) << 15;
1409*ec779b8eSAndroid Build Coastguard Worker             if (br->numBitsLeft() < 16 || br->getBits(1) != 1u) {
1410*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
1411*ec779b8eSAndroid Build Coastguard Worker             }
1412*ec779b8eSAndroid Build Coastguard Worker             PTS |= br->getBits(15);
1413*ec779b8eSAndroid Build Coastguard Worker             if (br->numBitsLeft() < 1 || br->getBits(1) != 1u) {
1414*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
1415*ec779b8eSAndroid Build Coastguard Worker             }
1416*ec779b8eSAndroid Build Coastguard Worker 
1417*ec779b8eSAndroid Build Coastguard Worker             ALOGV("PTS = 0x%016" PRIx64 " (%.2f)", PTS, PTS / 90000.0);
1418*ec779b8eSAndroid Build Coastguard Worker 
1419*ec779b8eSAndroid Build Coastguard Worker             optional_bytes_remaining -= 5;
1420*ec779b8eSAndroid Build Coastguard Worker 
1421*ec779b8eSAndroid Build Coastguard Worker             if (PTS_DTS_flags == 3) {
1422*ec779b8eSAndroid Build Coastguard Worker                 if (optional_bytes_remaining < 5u) {
1423*ec779b8eSAndroid Build Coastguard Worker                     return ERROR_MALFORMED;
1424*ec779b8eSAndroid Build Coastguard Worker                 }
1425*ec779b8eSAndroid Build Coastguard Worker 
1426*ec779b8eSAndroid Build Coastguard Worker                 if (br->numBitsLeft() < 7 || br->getBits(4) != 1u) {
1427*ec779b8eSAndroid Build Coastguard Worker                     return ERROR_MALFORMED;
1428*ec779b8eSAndroid Build Coastguard Worker                 }
1429*ec779b8eSAndroid Build Coastguard Worker 
1430*ec779b8eSAndroid Build Coastguard Worker                 DTS = ((uint64_t)br->getBits(3)) << 30;
1431*ec779b8eSAndroid Build Coastguard Worker                 if (br->numBitsLeft() < 16 || br->getBits(1) != 1u) {
1432*ec779b8eSAndroid Build Coastguard Worker                     return ERROR_MALFORMED;
1433*ec779b8eSAndroid Build Coastguard Worker                 }
1434*ec779b8eSAndroid Build Coastguard Worker                 DTS |= ((uint64_t)br->getBits(15)) << 15;
1435*ec779b8eSAndroid Build Coastguard Worker                 if (br->numBitsLeft() < 16 || br->getBits(1) != 1u) {
1436*ec779b8eSAndroid Build Coastguard Worker                     return ERROR_MALFORMED;
1437*ec779b8eSAndroid Build Coastguard Worker                 }
1438*ec779b8eSAndroid Build Coastguard Worker                 DTS |= br->getBits(15);
1439*ec779b8eSAndroid Build Coastguard Worker                 if (br->numBitsLeft() < 1 || br->getBits(1) != 1u) {
1440*ec779b8eSAndroid Build Coastguard Worker                     return ERROR_MALFORMED;
1441*ec779b8eSAndroid Build Coastguard Worker                 }
1442*ec779b8eSAndroid Build Coastguard Worker 
1443*ec779b8eSAndroid Build Coastguard Worker                 ALOGV("DTS = %" PRIu64, DTS);
1444*ec779b8eSAndroid Build Coastguard Worker 
1445*ec779b8eSAndroid Build Coastguard Worker                 optional_bytes_remaining -= 5;
1446*ec779b8eSAndroid Build Coastguard Worker             }
1447*ec779b8eSAndroid Build Coastguard Worker         }
1448*ec779b8eSAndroid Build Coastguard Worker 
1449*ec779b8eSAndroid Build Coastguard Worker         if (ESCR_flag) {
1450*ec779b8eSAndroid Build Coastguard Worker             if (optional_bytes_remaining < 6u) {
1451*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
1452*ec779b8eSAndroid Build Coastguard Worker             }
1453*ec779b8eSAndroid Build Coastguard Worker 
1454*ec779b8eSAndroid Build Coastguard Worker             if (br->numBitsLeft() < 5) {
1455*ec779b8eSAndroid Build Coastguard Worker                 ALOGE("Not enough data left in bitreader!");
1456*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
1457*ec779b8eSAndroid Build Coastguard Worker             }
1458*ec779b8eSAndroid Build Coastguard Worker             br->getBits(2);
1459*ec779b8eSAndroid Build Coastguard Worker 
1460*ec779b8eSAndroid Build Coastguard Worker             uint64_t ESCR = ((uint64_t)br->getBits(3)) << 30;
1461*ec779b8eSAndroid Build Coastguard Worker             if (br->numBitsLeft() < 16 || br->getBits(1) != 1u) {
1462*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
1463*ec779b8eSAndroid Build Coastguard Worker             }
1464*ec779b8eSAndroid Build Coastguard Worker             ESCR |= ((uint64_t)br->getBits(15)) << 15;
1465*ec779b8eSAndroid Build Coastguard Worker             if (br->numBitsLeft() < 16 || br->getBits(1) != 1u) {
1466*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
1467*ec779b8eSAndroid Build Coastguard Worker             }
1468*ec779b8eSAndroid Build Coastguard Worker             ESCR |= br->getBits(15);
1469*ec779b8eSAndroid Build Coastguard Worker             if (br->numBitsLeft() < 1 || br->getBits(1) != 1u) {
1470*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
1471*ec779b8eSAndroid Build Coastguard Worker             }
1472*ec779b8eSAndroid Build Coastguard Worker 
1473*ec779b8eSAndroid Build Coastguard Worker             ALOGV("ESCR = %" PRIu64, ESCR);
1474*ec779b8eSAndroid Build Coastguard Worker             if (br->numBitsLeft() < 10) {
1475*ec779b8eSAndroid Build Coastguard Worker                 ALOGE("Not enough data left in bitreader!");
1476*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
1477*ec779b8eSAndroid Build Coastguard Worker             }
1478*ec779b8eSAndroid Build Coastguard Worker             MY_LOGV("ESCR_extension = %u", br->getBits(9));
1479*ec779b8eSAndroid Build Coastguard Worker 
1480*ec779b8eSAndroid Build Coastguard Worker             if (br->getBits(1) != 1u) {
1481*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
1482*ec779b8eSAndroid Build Coastguard Worker             }
1483*ec779b8eSAndroid Build Coastguard Worker 
1484*ec779b8eSAndroid Build Coastguard Worker             optional_bytes_remaining -= 6;
1485*ec779b8eSAndroid Build Coastguard Worker         }
1486*ec779b8eSAndroid Build Coastguard Worker 
1487*ec779b8eSAndroid Build Coastguard Worker         if (ES_rate_flag) {
1488*ec779b8eSAndroid Build Coastguard Worker             if (optional_bytes_remaining < 3u) {
1489*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
1490*ec779b8eSAndroid Build Coastguard Worker             }
1491*ec779b8eSAndroid Build Coastguard Worker 
1492*ec779b8eSAndroid Build Coastguard Worker             if (br->numBitsLeft() < 1 || br->getBits(1) != 1u) {
1493*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
1494*ec779b8eSAndroid Build Coastguard Worker             }
1495*ec779b8eSAndroid Build Coastguard Worker             if (br->numBitsLeft() < 22) {
1496*ec779b8eSAndroid Build Coastguard Worker                 ALOGE("Not enough data left in bitreader!");
1497*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
1498*ec779b8eSAndroid Build Coastguard Worker             }
1499*ec779b8eSAndroid Build Coastguard Worker             MY_LOGV("ES_rate = %u", br->getBits(22));
1500*ec779b8eSAndroid Build Coastguard Worker             if (br->numBitsLeft() < 1 || br->getBits(1) != 1u) {
1501*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
1502*ec779b8eSAndroid Build Coastguard Worker             }
1503*ec779b8eSAndroid Build Coastguard Worker 
1504*ec779b8eSAndroid Build Coastguard Worker             optional_bytes_remaining -= 3;
1505*ec779b8eSAndroid Build Coastguard Worker         }
1506*ec779b8eSAndroid Build Coastguard Worker 
1507*ec779b8eSAndroid Build Coastguard Worker         if (!br->skipBits(optional_bytes_remaining * 8)) {
1508*ec779b8eSAndroid Build Coastguard Worker             ALOGE("Not enough data left in bitreader!");
1509*ec779b8eSAndroid Build Coastguard Worker             return ERROR_MALFORMED;
1510*ec779b8eSAndroid Build Coastguard Worker         }
1511*ec779b8eSAndroid Build Coastguard Worker 
1512*ec779b8eSAndroid Build Coastguard Worker         // ES data follows.
1513*ec779b8eSAndroid Build Coastguard Worker         int32_t pesOffset = br->data() - basePtr;
1514*ec779b8eSAndroid Build Coastguard Worker 
1515*ec779b8eSAndroid Build Coastguard Worker         if (PES_packet_length != 0) {
1516*ec779b8eSAndroid Build Coastguard Worker             if (PES_packet_length < PES_header_data_length + 3) {
1517*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
1518*ec779b8eSAndroid Build Coastguard Worker             }
1519*ec779b8eSAndroid Build Coastguard Worker 
1520*ec779b8eSAndroid Build Coastguard Worker             unsigned dataLength =
1521*ec779b8eSAndroid Build Coastguard Worker                 PES_packet_length - 3 - PES_header_data_length;
1522*ec779b8eSAndroid Build Coastguard Worker 
1523*ec779b8eSAndroid Build Coastguard Worker             if (br->numBitsLeft() < dataLength * 8) {
1524*ec779b8eSAndroid Build Coastguard Worker                 ALOGE("PES packet does not carry enough data to contain "
1525*ec779b8eSAndroid Build Coastguard Worker                      "payload. (numBitsLeft = %zu, required = %u)",
1526*ec779b8eSAndroid Build Coastguard Worker                      br->numBitsLeft(), dataLength * 8);
1527*ec779b8eSAndroid Build Coastguard Worker 
1528*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
1529*ec779b8eSAndroid Build Coastguard Worker             }
1530*ec779b8eSAndroid Build Coastguard Worker 
1531*ec779b8eSAndroid Build Coastguard Worker             ALOGV("There's %u bytes of payload, PES_packet_length=%u, offset=%d",
1532*ec779b8eSAndroid Build Coastguard Worker                     dataLength, PES_packet_length, pesOffset);
1533*ec779b8eSAndroid Build Coastguard Worker 
1534*ec779b8eSAndroid Build Coastguard Worker             onPayloadData(
1535*ec779b8eSAndroid Build Coastguard Worker                     PTS_DTS_flags, PTS, DTS, PES_scrambling_control,
1536*ec779b8eSAndroid Build Coastguard Worker                     br->data(), dataLength, pesOffset, event);
1537*ec779b8eSAndroid Build Coastguard Worker 
1538*ec779b8eSAndroid Build Coastguard Worker             if (!br->skipBits(dataLength * 8)) {
1539*ec779b8eSAndroid Build Coastguard Worker                 ALOGE("Not enough data left in bitreader!");
1540*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
1541*ec779b8eSAndroid Build Coastguard Worker             }
1542*ec779b8eSAndroid Build Coastguard Worker         } else {
1543*ec779b8eSAndroid Build Coastguard Worker             onPayloadData(
1544*ec779b8eSAndroid Build Coastguard Worker                     PTS_DTS_flags, PTS, DTS, PES_scrambling_control,
1545*ec779b8eSAndroid Build Coastguard Worker                     br->data(), br->numBitsLeft() / 8, pesOffset, event);
1546*ec779b8eSAndroid Build Coastguard Worker 
1547*ec779b8eSAndroid Build Coastguard Worker             size_t payloadSizeBits = br->numBitsLeft();
1548*ec779b8eSAndroid Build Coastguard Worker             if (payloadSizeBits % 8 != 0u) {
1549*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
1550*ec779b8eSAndroid Build Coastguard Worker             }
1551*ec779b8eSAndroid Build Coastguard Worker 
1552*ec779b8eSAndroid Build Coastguard Worker             ALOGV("There's %zu bytes of payload, offset=%d",
1553*ec779b8eSAndroid Build Coastguard Worker                     payloadSizeBits / 8, pesOffset);
1554*ec779b8eSAndroid Build Coastguard Worker         }
1555*ec779b8eSAndroid Build Coastguard Worker     } else if (stream_id == 0xbe) {  // padding_stream
1556*ec779b8eSAndroid Build Coastguard Worker         if (PES_packet_length == 0u || !br->skipBits(PES_packet_length * 8)) {
1557*ec779b8eSAndroid Build Coastguard Worker             return ERROR_MALFORMED;
1558*ec779b8eSAndroid Build Coastguard Worker         }
1559*ec779b8eSAndroid Build Coastguard Worker     } else {
1560*ec779b8eSAndroid Build Coastguard Worker         if (PES_packet_length == 0u || !br->skipBits(PES_packet_length * 8)) {
1561*ec779b8eSAndroid Build Coastguard Worker             return ERROR_MALFORMED;
1562*ec779b8eSAndroid Build Coastguard Worker         }
1563*ec779b8eSAndroid Build Coastguard Worker     }
1564*ec779b8eSAndroid Build Coastguard Worker 
1565*ec779b8eSAndroid Build Coastguard Worker     return OK;
1566*ec779b8eSAndroid Build Coastguard Worker }
1567*ec779b8eSAndroid Build Coastguard Worker 
getPesScramblingControl(ABitReader * br,int32_t * pesOffset)1568*ec779b8eSAndroid Build Coastguard Worker uint32_t ATSParser::Stream::getPesScramblingControl(
1569*ec779b8eSAndroid Build Coastguard Worker         ABitReader *br, int32_t *pesOffset) {
1570*ec779b8eSAndroid Build Coastguard Worker     if (br->numBitsLeft() < 24) {
1571*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Not enough data left in bitreader!");
1572*ec779b8eSAndroid Build Coastguard Worker         return 0;
1573*ec779b8eSAndroid Build Coastguard Worker     }
1574*ec779b8eSAndroid Build Coastguard Worker     unsigned packet_startcode_prefix = br->getBits(24);
1575*ec779b8eSAndroid Build Coastguard Worker 
1576*ec779b8eSAndroid Build Coastguard Worker     ALOGV("packet_startcode_prefix = 0x%08x", packet_startcode_prefix);
1577*ec779b8eSAndroid Build Coastguard Worker 
1578*ec779b8eSAndroid Build Coastguard Worker     if (packet_startcode_prefix != 1) {
1579*ec779b8eSAndroid Build Coastguard Worker         ALOGV("unit does not start with startcode.");
1580*ec779b8eSAndroid Build Coastguard Worker         return 0;
1581*ec779b8eSAndroid Build Coastguard Worker     }
1582*ec779b8eSAndroid Build Coastguard Worker 
1583*ec779b8eSAndroid Build Coastguard Worker     if (br->numBitsLeft() < 48) {
1584*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Not enough data left in bitreader!");
1585*ec779b8eSAndroid Build Coastguard Worker         return 0;
1586*ec779b8eSAndroid Build Coastguard Worker     }
1587*ec779b8eSAndroid Build Coastguard Worker 
1588*ec779b8eSAndroid Build Coastguard Worker     unsigned stream_id = br->getBits(8);
1589*ec779b8eSAndroid Build Coastguard Worker     ALOGV("stream_id = 0x%02x", stream_id);
1590*ec779b8eSAndroid Build Coastguard Worker 
1591*ec779b8eSAndroid Build Coastguard Worker     br->skipBits(16); // PES_packet_length
1592*ec779b8eSAndroid Build Coastguard Worker 
1593*ec779b8eSAndroid Build Coastguard Worker     if (stream_id != 0xbc  // program_stream_map
1594*ec779b8eSAndroid Build Coastguard Worker             && stream_id != 0xbe  // padding_stream
1595*ec779b8eSAndroid Build Coastguard Worker             && stream_id != 0xbf  // private_stream_2
1596*ec779b8eSAndroid Build Coastguard Worker             && stream_id != 0xf0  // ECM
1597*ec779b8eSAndroid Build Coastguard Worker             && stream_id != 0xf1  // EMM
1598*ec779b8eSAndroid Build Coastguard Worker             && stream_id != 0xff  // program_stream_directory
1599*ec779b8eSAndroid Build Coastguard Worker             && stream_id != 0xf2  // DSMCC
1600*ec779b8eSAndroid Build Coastguard Worker             && stream_id != 0xf8) {  // H.222.1 type E
1601*ec779b8eSAndroid Build Coastguard Worker         if (br->getBits(2) != 2u) {
1602*ec779b8eSAndroid Build Coastguard Worker             return 0;
1603*ec779b8eSAndroid Build Coastguard Worker         }
1604*ec779b8eSAndroid Build Coastguard Worker 
1605*ec779b8eSAndroid Build Coastguard Worker         unsigned PES_scrambling_control = br->getBits(2);
1606*ec779b8eSAndroid Build Coastguard Worker         ALOGV("PES_scrambling_control = %u", PES_scrambling_control);
1607*ec779b8eSAndroid Build Coastguard Worker 
1608*ec779b8eSAndroid Build Coastguard Worker         if (PES_scrambling_control == 0) {
1609*ec779b8eSAndroid Build Coastguard Worker             return 0;
1610*ec779b8eSAndroid Build Coastguard Worker         }
1611*ec779b8eSAndroid Build Coastguard Worker 
1612*ec779b8eSAndroid Build Coastguard Worker         br->skipBits(12); // don't care
1613*ec779b8eSAndroid Build Coastguard Worker 
1614*ec779b8eSAndroid Build Coastguard Worker         unsigned PES_header_data_length = br->getBits(8);
1615*ec779b8eSAndroid Build Coastguard Worker         ALOGV("PES_header_data_length = %u", PES_header_data_length);
1616*ec779b8eSAndroid Build Coastguard Worker 
1617*ec779b8eSAndroid Build Coastguard Worker         if (PES_header_data_length * 8 > br->numBitsLeft()) {
1618*ec779b8eSAndroid Build Coastguard Worker             return 0;
1619*ec779b8eSAndroid Build Coastguard Worker         }
1620*ec779b8eSAndroid Build Coastguard Worker 
1621*ec779b8eSAndroid Build Coastguard Worker         *pesOffset = 9 + PES_header_data_length;
1622*ec779b8eSAndroid Build Coastguard Worker         ALOGD("found PES_scrambling_control=%d, PES offset=%d",
1623*ec779b8eSAndroid Build Coastguard Worker                 PES_scrambling_control, *pesOffset);
1624*ec779b8eSAndroid Build Coastguard Worker         return PES_scrambling_control;
1625*ec779b8eSAndroid Build Coastguard Worker     }
1626*ec779b8eSAndroid Build Coastguard Worker 
1627*ec779b8eSAndroid Build Coastguard Worker     return 0;
1628*ec779b8eSAndroid Build Coastguard Worker }
1629*ec779b8eSAndroid Build Coastguard Worker 
flushScrambled(SyncEvent * event)1630*ec779b8eSAndroid Build Coastguard Worker status_t ATSParser::Stream::flushScrambled(SyncEvent *event) {
1631*ec779b8eSAndroid Build Coastguard Worker     if (mDescrambler == NULL) {
1632*ec779b8eSAndroid Build Coastguard Worker         ALOGE("received scrambled packets without descrambler!");
1633*ec779b8eSAndroid Build Coastguard Worker         return UNKNOWN_ERROR;
1634*ec779b8eSAndroid Build Coastguard Worker     }
1635*ec779b8eSAndroid Build Coastguard Worker 
1636*ec779b8eSAndroid Build Coastguard Worker     if (mDescrambledBuffer == NULL || mHidlMemory == NULL) {
1637*ec779b8eSAndroid Build Coastguard Worker         ALOGE("received scrambled packets without shared memory!");
1638*ec779b8eSAndroid Build Coastguard Worker 
1639*ec779b8eSAndroid Build Coastguard Worker         return UNKNOWN_ERROR;
1640*ec779b8eSAndroid Build Coastguard Worker     }
1641*ec779b8eSAndroid Build Coastguard Worker 
1642*ec779b8eSAndroid Build Coastguard Worker     int32_t pesOffset = 0;
1643*ec779b8eSAndroid Build Coastguard Worker     int32_t descrambleSubSamples = 0, descrambleBytes = 0;
1644*ec779b8eSAndroid Build Coastguard Worker     uint32_t tsScramblingControl = 0, pesScramblingControl = 0;
1645*ec779b8eSAndroid Build Coastguard Worker 
1646*ec779b8eSAndroid Build Coastguard Worker     // First, go over subsamples to find TS-level scrambling key id, and
1647*ec779b8eSAndroid Build Coastguard Worker     // calculate how many subsample we need to descramble (assuming we don't
1648*ec779b8eSAndroid Build Coastguard Worker     // have PES-level scrambling).
1649*ec779b8eSAndroid Build Coastguard Worker     for (auto it = mSubSamples.begin(); it != mSubSamples.end(); it++) {
1650*ec779b8eSAndroid Build Coastguard Worker         if (it->transport_scrambling_mode != 0) {
1651*ec779b8eSAndroid Build Coastguard Worker             // TODO: handle keyId change, use the first non-zero keyId for now.
1652*ec779b8eSAndroid Build Coastguard Worker             if (tsScramblingControl == 0) {
1653*ec779b8eSAndroid Build Coastguard Worker                 tsScramblingControl = it->transport_scrambling_mode;
1654*ec779b8eSAndroid Build Coastguard Worker             }
1655*ec779b8eSAndroid Build Coastguard Worker         }
1656*ec779b8eSAndroid Build Coastguard Worker         if (tsScramblingControl == 0 || descrambleSubSamples == 0
1657*ec779b8eSAndroid Build Coastguard Worker                 || !mQueue->isScrambled()) {
1658*ec779b8eSAndroid Build Coastguard Worker             descrambleSubSamples++;
1659*ec779b8eSAndroid Build Coastguard Worker             descrambleBytes += it->subSampleSize;
1660*ec779b8eSAndroid Build Coastguard Worker         }
1661*ec779b8eSAndroid Build Coastguard Worker     }
1662*ec779b8eSAndroid Build Coastguard Worker     // If not scrambled at TS-level, check PES-level scrambling
1663*ec779b8eSAndroid Build Coastguard Worker     if (tsScramblingControl == 0) {
1664*ec779b8eSAndroid Build Coastguard Worker         ABitReader br(mBuffer->data(), mBuffer->size());
1665*ec779b8eSAndroid Build Coastguard Worker         pesScramblingControl = getPesScramblingControl(&br, &pesOffset);
1666*ec779b8eSAndroid Build Coastguard Worker         // If not scrambled at PES-level either, or scrambled at PES-level but
1667*ec779b8eSAndroid Build Coastguard Worker         // requires output to remain scrambled, we don't need to descramble
1668*ec779b8eSAndroid Build Coastguard Worker         // anything.
1669*ec779b8eSAndroid Build Coastguard Worker         if (pesScramblingControl == 0 || mQueue->isScrambled()) {
1670*ec779b8eSAndroid Build Coastguard Worker             descrambleSubSamples = 0;
1671*ec779b8eSAndroid Build Coastguard Worker             descrambleBytes = 0;
1672*ec779b8eSAndroid Build Coastguard Worker         }
1673*ec779b8eSAndroid Build Coastguard Worker     }
1674*ec779b8eSAndroid Build Coastguard Worker 
1675*ec779b8eSAndroid Build Coastguard Worker     uint32_t sctrl = tsScramblingControl != 0 ?
1676*ec779b8eSAndroid Build Coastguard Worker             tsScramblingControl : pesScramblingControl;
1677*ec779b8eSAndroid Build Coastguard Worker     if (mQueue->isScrambled()) {
1678*ec779b8eSAndroid Build Coastguard Worker         sctrl |= DescramblerPlugin::kScrambling_Flag_PesHeader;
1679*ec779b8eSAndroid Build Coastguard Worker     }
1680*ec779b8eSAndroid Build Coastguard Worker 
1681*ec779b8eSAndroid Build Coastguard Worker     // Perform the 1st pass descrambling if needed
1682*ec779b8eSAndroid Build Coastguard Worker     if (descrambleBytes > 0) {
1683*ec779b8eSAndroid Build Coastguard Worker         memcpy(mDescrambledBuffer->data(), mBuffer->data(), descrambleBytes);
1684*ec779b8eSAndroid Build Coastguard Worker         mDescrambledBuffer->setRange(0, mBuffer->size());
1685*ec779b8eSAndroid Build Coastguard Worker 
1686*ec779b8eSAndroid Build Coastguard Worker         hidl_vec<SubSample> subSamples;
1687*ec779b8eSAndroid Build Coastguard Worker         subSamples.resize(descrambleSubSamples);
1688*ec779b8eSAndroid Build Coastguard Worker 
1689*ec779b8eSAndroid Build Coastguard Worker         int32_t i = 0;
1690*ec779b8eSAndroid Build Coastguard Worker         for (auto it = mSubSamples.begin();
1691*ec779b8eSAndroid Build Coastguard Worker                 it != mSubSamples.end() && i < descrambleSubSamples; it++, i++) {
1692*ec779b8eSAndroid Build Coastguard Worker             if (it->transport_scrambling_mode != 0 || pesScramblingControl != 0) {
1693*ec779b8eSAndroid Build Coastguard Worker                 subSamples[i].numBytesOfClearData = 0;
1694*ec779b8eSAndroid Build Coastguard Worker                 subSamples[i].numBytesOfEncryptedData = it->subSampleSize;
1695*ec779b8eSAndroid Build Coastguard Worker             } else {
1696*ec779b8eSAndroid Build Coastguard Worker                 subSamples[i].numBytesOfClearData = it->subSampleSize;
1697*ec779b8eSAndroid Build Coastguard Worker                 subSamples[i].numBytesOfEncryptedData = 0;
1698*ec779b8eSAndroid Build Coastguard Worker             }
1699*ec779b8eSAndroid Build Coastguard Worker         }
1700*ec779b8eSAndroid Build Coastguard Worker 
1701*ec779b8eSAndroid Build Coastguard Worker         // If scrambled at PES-level, PES header is in the clear
1702*ec779b8eSAndroid Build Coastguard Worker         if (pesScramblingControl != 0) {
1703*ec779b8eSAndroid Build Coastguard Worker             subSamples[0].numBytesOfClearData = pesOffset;
1704*ec779b8eSAndroid Build Coastguard Worker             subSamples[0].numBytesOfEncryptedData -= pesOffset;
1705*ec779b8eSAndroid Build Coastguard Worker         }
1706*ec779b8eSAndroid Build Coastguard Worker 
1707*ec779b8eSAndroid Build Coastguard Worker         Status status = Status::OK;
1708*ec779b8eSAndroid Build Coastguard Worker         uint32_t bytesWritten = 0;
1709*ec779b8eSAndroid Build Coastguard Worker         hidl_string detailedError;
1710*ec779b8eSAndroid Build Coastguard Worker 
1711*ec779b8eSAndroid Build Coastguard Worker         DestinationBuffer dstBuffer;
1712*ec779b8eSAndroid Build Coastguard Worker         dstBuffer.type = BufferType::SHARED_MEMORY;
1713*ec779b8eSAndroid Build Coastguard Worker         dstBuffer.nonsecureMemory = mDescramblerSrcBuffer;
1714*ec779b8eSAndroid Build Coastguard Worker 
1715*ec779b8eSAndroid Build Coastguard Worker         auto returnVoid = mDescrambler->descramble(
1716*ec779b8eSAndroid Build Coastguard Worker                 (ScramblingControl) sctrl,
1717*ec779b8eSAndroid Build Coastguard Worker                 subSamples,
1718*ec779b8eSAndroid Build Coastguard Worker                 mDescramblerSrcBuffer,
1719*ec779b8eSAndroid Build Coastguard Worker                 0 /*srcOffset*/,
1720*ec779b8eSAndroid Build Coastguard Worker                 dstBuffer,
1721*ec779b8eSAndroid Build Coastguard Worker                 0 /*dstOffset*/,
1722*ec779b8eSAndroid Build Coastguard Worker                 [&status, &bytesWritten, &detailedError] (
1723*ec779b8eSAndroid Build Coastguard Worker                         Status _status, uint32_t _bytesWritten,
1724*ec779b8eSAndroid Build Coastguard Worker                         const hidl_string& _detailedError) {
1725*ec779b8eSAndroid Build Coastguard Worker                     status = _status;
1726*ec779b8eSAndroid Build Coastguard Worker                     bytesWritten = _bytesWritten;
1727*ec779b8eSAndroid Build Coastguard Worker                     detailedError = _detailedError;
1728*ec779b8eSAndroid Build Coastguard Worker                 });
1729*ec779b8eSAndroid Build Coastguard Worker 
1730*ec779b8eSAndroid Build Coastguard Worker         if (!returnVoid.isOk() || status != Status::OK) {
1731*ec779b8eSAndroid Build Coastguard Worker             ALOGE("[stream %d] descramble failed, trans=%s, status=%d",
1732*ec779b8eSAndroid Build Coastguard Worker                     mElementaryPID, returnVoid.description().c_str(), status);
1733*ec779b8eSAndroid Build Coastguard Worker             return UNKNOWN_ERROR;
1734*ec779b8eSAndroid Build Coastguard Worker         }
1735*ec779b8eSAndroid Build Coastguard Worker 
1736*ec779b8eSAndroid Build Coastguard Worker         ALOGV("[stream %d] descramble succeeded, %d bytes",
1737*ec779b8eSAndroid Build Coastguard Worker                 mElementaryPID, bytesWritten);
1738*ec779b8eSAndroid Build Coastguard Worker 
1739*ec779b8eSAndroid Build Coastguard Worker         // Set descrambleBytes to the returned result.
1740*ec779b8eSAndroid Build Coastguard Worker         // Note that this might be smaller than the total length of input data.
1741*ec779b8eSAndroid Build Coastguard Worker         // (eg. when we're descrambling the PES header portion of a secure stream,
1742*ec779b8eSAndroid Build Coastguard Worker         // the plugin might cut it off right after the PES header.)
1743*ec779b8eSAndroid Build Coastguard Worker         descrambleBytes = bytesWritten;
1744*ec779b8eSAndroid Build Coastguard Worker     }
1745*ec779b8eSAndroid Build Coastguard Worker 
1746*ec779b8eSAndroid Build Coastguard Worker     // |buffer| points to the buffer from which we'd parse the PES header.
1747*ec779b8eSAndroid Build Coastguard Worker     // When the output stream is scrambled, it points to mDescrambledBuffer
1748*ec779b8eSAndroid Build Coastguard Worker     // (unless all packets in this PES are actually clear, in which case,
1749*ec779b8eSAndroid Build Coastguard Worker     // it points to mBuffer since we never copied into mDescrambledBuffer).
1750*ec779b8eSAndroid Build Coastguard Worker     // When the output stream is clear, it points to mBuffer, and we'll
1751*ec779b8eSAndroid Build Coastguard Worker     // copy all descrambled data back to mBuffer.
1752*ec779b8eSAndroid Build Coastguard Worker     sp<ABuffer> buffer = mBuffer;
1753*ec779b8eSAndroid Build Coastguard Worker     if (mQueue->isScrambled()) {
1754*ec779b8eSAndroid Build Coastguard Worker         // Queue subSample info for scrambled queue
1755*ec779b8eSAndroid Build Coastguard Worker         sp<ABuffer> clearSizesBuffer = new ABuffer(mSubSamples.size() * 4);
1756*ec779b8eSAndroid Build Coastguard Worker         sp<ABuffer> encSizesBuffer = new ABuffer(mSubSamples.size() * 4);
1757*ec779b8eSAndroid Build Coastguard Worker         int32_t *clearSizePtr = (int32_t*)clearSizesBuffer->data();
1758*ec779b8eSAndroid Build Coastguard Worker         int32_t *encSizePtr = (int32_t*)encSizesBuffer->data();
1759*ec779b8eSAndroid Build Coastguard Worker         int32_t isSync = 0;
1760*ec779b8eSAndroid Build Coastguard Worker         int32_t i = 0;
1761*ec779b8eSAndroid Build Coastguard Worker         for (auto it = mSubSamples.begin();
1762*ec779b8eSAndroid Build Coastguard Worker                 it != mSubSamples.end(); it++, i++) {
1763*ec779b8eSAndroid Build Coastguard Worker             if ((it->transport_scrambling_mode == 0
1764*ec779b8eSAndroid Build Coastguard Worker                     && pesScramblingControl == 0)) {
1765*ec779b8eSAndroid Build Coastguard Worker                 clearSizePtr[i] = it->subSampleSize;
1766*ec779b8eSAndroid Build Coastguard Worker                 encSizePtr[i] = 0;
1767*ec779b8eSAndroid Build Coastguard Worker             } else {
1768*ec779b8eSAndroid Build Coastguard Worker                 clearSizePtr[i] = 0;
1769*ec779b8eSAndroid Build Coastguard Worker                 encSizePtr[i] = it->subSampleSize;
1770*ec779b8eSAndroid Build Coastguard Worker             }
1771*ec779b8eSAndroid Build Coastguard Worker             isSync |= it->random_access_indicator;
1772*ec779b8eSAndroid Build Coastguard Worker         }
1773*ec779b8eSAndroid Build Coastguard Worker 
1774*ec779b8eSAndroid Build Coastguard Worker         // If scrambled at PES-level, PES header is in the clear
1775*ec779b8eSAndroid Build Coastguard Worker         if (pesScramblingControl != 0) {
1776*ec779b8eSAndroid Build Coastguard Worker             clearSizePtr[0] = pesOffset;
1777*ec779b8eSAndroid Build Coastguard Worker             encSizePtr[0] -= pesOffset;
1778*ec779b8eSAndroid Build Coastguard Worker         }
1779*ec779b8eSAndroid Build Coastguard Worker         // Pass the original TS subsample size now. The PES header adjust
1780*ec779b8eSAndroid Build Coastguard Worker         // will be applied when the scrambled AU is dequeued.
1781*ec779b8eSAndroid Build Coastguard Worker         // Note that if descrambleBytes is 0, it means this PES contains only
1782*ec779b8eSAndroid Build Coastguard Worker         // all ts packets, leadingClearBytes is entire buffer size.
1783*ec779b8eSAndroid Build Coastguard Worker         mQueue->appendScrambledData(
1784*ec779b8eSAndroid Build Coastguard Worker                 mBuffer->data(), mBuffer->size(),
1785*ec779b8eSAndroid Build Coastguard Worker                 (descrambleBytes > 0) ? descrambleBytes : mBuffer->size(),
1786*ec779b8eSAndroid Build Coastguard Worker                 sctrl, isSync, clearSizesBuffer, encSizesBuffer);
1787*ec779b8eSAndroid Build Coastguard Worker 
1788*ec779b8eSAndroid Build Coastguard Worker         if (descrambleBytes > 0) {
1789*ec779b8eSAndroid Build Coastguard Worker             buffer = mDescrambledBuffer;
1790*ec779b8eSAndroid Build Coastguard Worker         }
1791*ec779b8eSAndroid Build Coastguard Worker     } else {
1792*ec779b8eSAndroid Build Coastguard Worker         memcpy(mBuffer->data(), mDescrambledBuffer->data(), descrambleBytes);
1793*ec779b8eSAndroid Build Coastguard Worker     }
1794*ec779b8eSAndroid Build Coastguard Worker 
1795*ec779b8eSAndroid Build Coastguard Worker     ABitReader br(buffer->data(), buffer->size());
1796*ec779b8eSAndroid Build Coastguard Worker     status_t err = parsePES(&br, event);
1797*ec779b8eSAndroid Build Coastguard Worker 
1798*ec779b8eSAndroid Build Coastguard Worker     if (err != OK) {
1799*ec779b8eSAndroid Build Coastguard Worker         ALOGE("[stream %d] failed to parse descrambled PES, err=%d",
1800*ec779b8eSAndroid Build Coastguard Worker                 mElementaryPID, err);
1801*ec779b8eSAndroid Build Coastguard Worker     }
1802*ec779b8eSAndroid Build Coastguard Worker 
1803*ec779b8eSAndroid Build Coastguard Worker     return err;
1804*ec779b8eSAndroid Build Coastguard Worker }
1805*ec779b8eSAndroid Build Coastguard Worker 
1806*ec779b8eSAndroid Build Coastguard Worker 
flush(SyncEvent * event)1807*ec779b8eSAndroid Build Coastguard Worker status_t ATSParser::Stream::flush(SyncEvent *event) {
1808*ec779b8eSAndroid Build Coastguard Worker     if (mBuffer == NULL || mBuffer->size() == 0) {
1809*ec779b8eSAndroid Build Coastguard Worker         return OK;
1810*ec779b8eSAndroid Build Coastguard Worker     }
1811*ec779b8eSAndroid Build Coastguard Worker 
1812*ec779b8eSAndroid Build Coastguard Worker     ALOGV("flushing stream 0x%04x size = %zu", mElementaryPID, mBuffer->size());
1813*ec779b8eSAndroid Build Coastguard Worker 
1814*ec779b8eSAndroid Build Coastguard Worker     status_t err = OK;
1815*ec779b8eSAndroid Build Coastguard Worker     if (mScrambled) {
1816*ec779b8eSAndroid Build Coastguard Worker         err = flushScrambled(event);
1817*ec779b8eSAndroid Build Coastguard Worker         mSubSamples.clear();
1818*ec779b8eSAndroid Build Coastguard Worker     } else {
1819*ec779b8eSAndroid Build Coastguard Worker         ABitReader br(mBuffer->data(), mBuffer->size());
1820*ec779b8eSAndroid Build Coastguard Worker         err = parsePES(&br, event);
1821*ec779b8eSAndroid Build Coastguard Worker     }
1822*ec779b8eSAndroid Build Coastguard Worker 
1823*ec779b8eSAndroid Build Coastguard Worker     mBuffer->setRange(0, 0);
1824*ec779b8eSAndroid Build Coastguard Worker 
1825*ec779b8eSAndroid Build Coastguard Worker     return err;
1826*ec779b8eSAndroid Build Coastguard Worker }
1827*ec779b8eSAndroid Build Coastguard Worker 
addAudioPresentations(const sp<ABuffer> & buffer)1828*ec779b8eSAndroid Build Coastguard Worker void ATSParser::Stream::addAudioPresentations(const sp<ABuffer> &buffer) {
1829*ec779b8eSAndroid Build Coastguard Worker     std::ostringstream outStream(std::ios::out);
1830*ec779b8eSAndroid Build Coastguard Worker     serializeAudioPresentations(mAudioPresentations, &outStream);
1831*ec779b8eSAndroid Build Coastguard Worker     sp<ABuffer> ap = ABuffer::CreateAsCopy(outStream.str().data(), outStream.str().size());
1832*ec779b8eSAndroid Build Coastguard Worker     buffer->meta()->setBuffer("audio-presentation-info", ap);
1833*ec779b8eSAndroid Build Coastguard Worker }
1834*ec779b8eSAndroid Build Coastguard Worker 
onPayloadData(unsigned PTS_DTS_flags,uint64_t PTS,uint64_t,unsigned PES_scrambling_control,const uint8_t * data,size_t size,int32_t payloadOffset,SyncEvent * event)1835*ec779b8eSAndroid Build Coastguard Worker void ATSParser::Stream::onPayloadData(
1836*ec779b8eSAndroid Build Coastguard Worker         unsigned PTS_DTS_flags, uint64_t PTS, uint64_t /* DTS */,
1837*ec779b8eSAndroid Build Coastguard Worker         unsigned PES_scrambling_control,
1838*ec779b8eSAndroid Build Coastguard Worker         const uint8_t *data, size_t size,
1839*ec779b8eSAndroid Build Coastguard Worker         int32_t payloadOffset, SyncEvent *event) {
1840*ec779b8eSAndroid Build Coastguard Worker #if 0
1841*ec779b8eSAndroid Build Coastguard Worker     ALOGI("payload streamType 0x%02x, PTS = 0x%016llx, dPTS = %lld",
1842*ec779b8eSAndroid Build Coastguard Worker           mStreamType,
1843*ec779b8eSAndroid Build Coastguard Worker           PTS,
1844*ec779b8eSAndroid Build Coastguard Worker           (int64_t)PTS - mPrevPTS);
1845*ec779b8eSAndroid Build Coastguard Worker     mPrevPTS = PTS;
1846*ec779b8eSAndroid Build Coastguard Worker #endif
1847*ec779b8eSAndroid Build Coastguard Worker 
1848*ec779b8eSAndroid Build Coastguard Worker     ALOGV("onPayloadData mStreamType=0x%02x size: %zu", mStreamType, size);
1849*ec779b8eSAndroid Build Coastguard Worker 
1850*ec779b8eSAndroid Build Coastguard Worker     int64_t timeUs = 0LL;  // no presentation timestamp available.
1851*ec779b8eSAndroid Build Coastguard Worker     if (PTS_DTS_flags == 2 || PTS_DTS_flags == 3) {
1852*ec779b8eSAndroid Build Coastguard Worker         timeUs = mProgram->convertPTSToTimestamp(PTS);
1853*ec779b8eSAndroid Build Coastguard Worker     }
1854*ec779b8eSAndroid Build Coastguard Worker 
1855*ec779b8eSAndroid Build Coastguard Worker     status_t err = mQueue->appendData(
1856*ec779b8eSAndroid Build Coastguard Worker             data, size, timeUs, payloadOffset, PES_scrambling_control);
1857*ec779b8eSAndroid Build Coastguard Worker 
1858*ec779b8eSAndroid Build Coastguard Worker     if (mEOSReached) {
1859*ec779b8eSAndroid Build Coastguard Worker         mQueue->signalEOS();
1860*ec779b8eSAndroid Build Coastguard Worker     }
1861*ec779b8eSAndroid Build Coastguard Worker 
1862*ec779b8eSAndroid Build Coastguard Worker     if (err != OK) {
1863*ec779b8eSAndroid Build Coastguard Worker         return;
1864*ec779b8eSAndroid Build Coastguard Worker     }
1865*ec779b8eSAndroid Build Coastguard Worker 
1866*ec779b8eSAndroid Build Coastguard Worker     sp<ABuffer> accessUnit;
1867*ec779b8eSAndroid Build Coastguard Worker     bool found = false;
1868*ec779b8eSAndroid Build Coastguard Worker     while ((accessUnit = mQueue->dequeueAccessUnit()) != NULL) {
1869*ec779b8eSAndroid Build Coastguard Worker         if (mSource == NULL) {
1870*ec779b8eSAndroid Build Coastguard Worker             sp<MetaData> meta = mQueue->getFormat();
1871*ec779b8eSAndroid Build Coastguard Worker 
1872*ec779b8eSAndroid Build Coastguard Worker             if (meta != NULL) {
1873*ec779b8eSAndroid Build Coastguard Worker                 ALOGV("Stream PID 0x%08x of type 0x%02x now has data.",
1874*ec779b8eSAndroid Build Coastguard Worker                      mElementaryPID, mStreamType);
1875*ec779b8eSAndroid Build Coastguard Worker 
1876*ec779b8eSAndroid Build Coastguard Worker                 const char *mime;
1877*ec779b8eSAndroid Build Coastguard Worker                 if (meta->findCString(kKeyMIMEType, &mime)
1878*ec779b8eSAndroid Build Coastguard Worker                         && !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1879*ec779b8eSAndroid Build Coastguard Worker                     int32_t sync = 0;
1880*ec779b8eSAndroid Build Coastguard Worker                     if (!accessUnit->meta()->findInt32("isSync", &sync) || !sync) {
1881*ec779b8eSAndroid Build Coastguard Worker                         continue;
1882*ec779b8eSAndroid Build Coastguard Worker                     }
1883*ec779b8eSAndroid Build Coastguard Worker                 }
1884*ec779b8eSAndroid Build Coastguard Worker                 mSource = new AnotherPacketSource(meta);
1885*ec779b8eSAndroid Build Coastguard Worker                 if (mAudioPresentations.size() > 0) {
1886*ec779b8eSAndroid Build Coastguard Worker                     addAudioPresentations(accessUnit);
1887*ec779b8eSAndroid Build Coastguard Worker                 }
1888*ec779b8eSAndroid Build Coastguard Worker                 mSource->queueAccessUnit(accessUnit);
1889*ec779b8eSAndroid Build Coastguard Worker                 ALOGV("onPayloadData: created AnotherPacketSource PID 0x%08x of type 0x%02x",
1890*ec779b8eSAndroid Build Coastguard Worker                         mElementaryPID, mStreamType);
1891*ec779b8eSAndroid Build Coastguard Worker             }
1892*ec779b8eSAndroid Build Coastguard Worker         } else if (mQueue->getFormat() != NULL) {
1893*ec779b8eSAndroid Build Coastguard Worker             // After a discontinuity we invalidate the queue's format
1894*ec779b8eSAndroid Build Coastguard Worker             // and won't enqueue any access units to the source until
1895*ec779b8eSAndroid Build Coastguard Worker             // the queue has reestablished the new format.
1896*ec779b8eSAndroid Build Coastguard Worker 
1897*ec779b8eSAndroid Build Coastguard Worker             if (mSource->getFormat() == NULL) {
1898*ec779b8eSAndroid Build Coastguard Worker                 mSource->setFormat(mQueue->getFormat());
1899*ec779b8eSAndroid Build Coastguard Worker             }
1900*ec779b8eSAndroid Build Coastguard Worker             if (mAudioPresentations.size() > 0) {
1901*ec779b8eSAndroid Build Coastguard Worker                 addAudioPresentations(accessUnit);
1902*ec779b8eSAndroid Build Coastguard Worker             }
1903*ec779b8eSAndroid Build Coastguard Worker             mSource->queueAccessUnit(accessUnit);
1904*ec779b8eSAndroid Build Coastguard Worker         }
1905*ec779b8eSAndroid Build Coastguard Worker 
1906*ec779b8eSAndroid Build Coastguard Worker         // Every access unit has a pesStartOffset queued in |mPesStartOffsets|.
1907*ec779b8eSAndroid Build Coastguard Worker         off64_t pesStartOffset = -1;
1908*ec779b8eSAndroid Build Coastguard Worker         if (!mPesStartOffsets.empty()) {
1909*ec779b8eSAndroid Build Coastguard Worker             pesStartOffset = *mPesStartOffsets.begin();
1910*ec779b8eSAndroid Build Coastguard Worker             mPesStartOffsets.erase(mPesStartOffsets.begin());
1911*ec779b8eSAndroid Build Coastguard Worker         }
1912*ec779b8eSAndroid Build Coastguard Worker 
1913*ec779b8eSAndroid Build Coastguard Worker         if (pesStartOffset >= 0 && (event != NULL) && !found && mQueue->getFormat() != NULL) {
1914*ec779b8eSAndroid Build Coastguard Worker             int32_t sync = 0;
1915*ec779b8eSAndroid Build Coastguard Worker             if (accessUnit->meta()->findInt32("isSync", &sync) && sync) {
1916*ec779b8eSAndroid Build Coastguard Worker                 int64_t timeUs;
1917*ec779b8eSAndroid Build Coastguard Worker                 if (accessUnit->meta()->findInt64("timeUs", &timeUs)) {
1918*ec779b8eSAndroid Build Coastguard Worker                     found = true;
1919*ec779b8eSAndroid Build Coastguard Worker                     event->init(pesStartOffset, mSource, timeUs, getSourceType());
1920*ec779b8eSAndroid Build Coastguard Worker                 }
1921*ec779b8eSAndroid Build Coastguard Worker             }
1922*ec779b8eSAndroid Build Coastguard Worker         }
1923*ec779b8eSAndroid Build Coastguard Worker     }
1924*ec779b8eSAndroid Build Coastguard Worker }
1925*ec779b8eSAndroid Build Coastguard Worker 
getSourceType()1926*ec779b8eSAndroid Build Coastguard Worker ATSParser::SourceType ATSParser::Stream::getSourceType() {
1927*ec779b8eSAndroid Build Coastguard Worker     if (isVideo()) {
1928*ec779b8eSAndroid Build Coastguard Worker         return VIDEO;
1929*ec779b8eSAndroid Build Coastguard Worker     } else if (isAudio()) {
1930*ec779b8eSAndroid Build Coastguard Worker         return AUDIO;
1931*ec779b8eSAndroid Build Coastguard Worker     } else if (isMeta()) {
1932*ec779b8eSAndroid Build Coastguard Worker         return META;
1933*ec779b8eSAndroid Build Coastguard Worker     }
1934*ec779b8eSAndroid Build Coastguard Worker     return NUM_SOURCE_TYPES;
1935*ec779b8eSAndroid Build Coastguard Worker }
1936*ec779b8eSAndroid Build Coastguard Worker 
getSource(SourceType type)1937*ec779b8eSAndroid Build Coastguard Worker sp<AnotherPacketSource> ATSParser::Stream::getSource(SourceType type) {
1938*ec779b8eSAndroid Build Coastguard Worker     switch (type) {
1939*ec779b8eSAndroid Build Coastguard Worker         case VIDEO:
1940*ec779b8eSAndroid Build Coastguard Worker         {
1941*ec779b8eSAndroid Build Coastguard Worker             if (isVideo()) {
1942*ec779b8eSAndroid Build Coastguard Worker                 return mSource;
1943*ec779b8eSAndroid Build Coastguard Worker             }
1944*ec779b8eSAndroid Build Coastguard Worker             break;
1945*ec779b8eSAndroid Build Coastguard Worker         }
1946*ec779b8eSAndroid Build Coastguard Worker 
1947*ec779b8eSAndroid Build Coastguard Worker         case AUDIO:
1948*ec779b8eSAndroid Build Coastguard Worker         {
1949*ec779b8eSAndroid Build Coastguard Worker             if (isAudio()) {
1950*ec779b8eSAndroid Build Coastguard Worker                 return mSource;
1951*ec779b8eSAndroid Build Coastguard Worker             }
1952*ec779b8eSAndroid Build Coastguard Worker             break;
1953*ec779b8eSAndroid Build Coastguard Worker         }
1954*ec779b8eSAndroid Build Coastguard Worker 
1955*ec779b8eSAndroid Build Coastguard Worker         case META:
1956*ec779b8eSAndroid Build Coastguard Worker         {
1957*ec779b8eSAndroid Build Coastguard Worker             if (isMeta()) {
1958*ec779b8eSAndroid Build Coastguard Worker                 return mSource;
1959*ec779b8eSAndroid Build Coastguard Worker             }
1960*ec779b8eSAndroid Build Coastguard Worker             break;
1961*ec779b8eSAndroid Build Coastguard Worker         }
1962*ec779b8eSAndroid Build Coastguard Worker 
1963*ec779b8eSAndroid Build Coastguard Worker         default:
1964*ec779b8eSAndroid Build Coastguard Worker             break;
1965*ec779b8eSAndroid Build Coastguard Worker     }
1966*ec779b8eSAndroid Build Coastguard Worker 
1967*ec779b8eSAndroid Build Coastguard Worker     return NULL;
1968*ec779b8eSAndroid Build Coastguard Worker }
1969*ec779b8eSAndroid Build Coastguard Worker 
setCasInfo(int32_t systemId,const sp<IDescrambler> & descrambler,const std::vector<uint8_t> & sessionId)1970*ec779b8eSAndroid Build Coastguard Worker void ATSParser::Stream::setCasInfo(
1971*ec779b8eSAndroid Build Coastguard Worker         int32_t systemId, const sp<IDescrambler> &descrambler,
1972*ec779b8eSAndroid Build Coastguard Worker         const std::vector<uint8_t> &sessionId) {
1973*ec779b8eSAndroid Build Coastguard Worker     if (mSource != NULL && mDescrambler == NULL && descrambler != NULL) {
1974*ec779b8eSAndroid Build Coastguard Worker         signalDiscontinuity(DISCONTINUITY_FORMAT_ONLY, NULL);
1975*ec779b8eSAndroid Build Coastguard Worker         mDescrambler = descrambler;
1976*ec779b8eSAndroid Build Coastguard Worker         if (mQueue->isScrambled()) {
1977*ec779b8eSAndroid Build Coastguard Worker             mQueue->setCasInfo(systemId, sessionId);
1978*ec779b8eSAndroid Build Coastguard Worker         }
1979*ec779b8eSAndroid Build Coastguard Worker     }
1980*ec779b8eSAndroid Build Coastguard Worker }
1981*ec779b8eSAndroid Build Coastguard Worker 
1982*ec779b8eSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
1983*ec779b8eSAndroid Build Coastguard Worker 
ATSParser(uint32_t flags)1984*ec779b8eSAndroid Build Coastguard Worker ATSParser::ATSParser(uint32_t flags)
1985*ec779b8eSAndroid Build Coastguard Worker     : mFlags(flags),
1986*ec779b8eSAndroid Build Coastguard Worker       mAbsoluteTimeAnchorUs(-1LL),
1987*ec779b8eSAndroid Build Coastguard Worker       mTimeOffsetValid(false),
1988*ec779b8eSAndroid Build Coastguard Worker       mTimeOffsetUs(0LL),
1989*ec779b8eSAndroid Build Coastguard Worker       mLastRecoveredPTS(-1LL),
1990*ec779b8eSAndroid Build Coastguard Worker       mNumTSPacketsParsed(0),
1991*ec779b8eSAndroid Build Coastguard Worker       mNumPCRs(0) {
1992*ec779b8eSAndroid Build Coastguard Worker     mPSISections.add(0 /* PID */, new PSISection);
1993*ec779b8eSAndroid Build Coastguard Worker     mCasManager = new CasManager();
1994*ec779b8eSAndroid Build Coastguard Worker }
1995*ec779b8eSAndroid Build Coastguard Worker 
~ATSParser()1996*ec779b8eSAndroid Build Coastguard Worker ATSParser::~ATSParser() {
1997*ec779b8eSAndroid Build Coastguard Worker }
1998*ec779b8eSAndroid Build Coastguard Worker 
feedTSPacket(const void * data,size_t size,SyncEvent * event)1999*ec779b8eSAndroid Build Coastguard Worker status_t ATSParser::feedTSPacket(const void *data, size_t size,
2000*ec779b8eSAndroid Build Coastguard Worker         SyncEvent *event) {
2001*ec779b8eSAndroid Build Coastguard Worker     if (size != kTSPacketSize) {
2002*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Wrong TS packet size");
2003*ec779b8eSAndroid Build Coastguard Worker         return BAD_VALUE;
2004*ec779b8eSAndroid Build Coastguard Worker     }
2005*ec779b8eSAndroid Build Coastguard Worker 
2006*ec779b8eSAndroid Build Coastguard Worker     ABitReader br((const uint8_t *)data, kTSPacketSize);
2007*ec779b8eSAndroid Build Coastguard Worker     return parseTS(&br, event);
2008*ec779b8eSAndroid Build Coastguard Worker }
2009*ec779b8eSAndroid Build Coastguard Worker 
setMediaCas(const sp<ICas> & cas)2010*ec779b8eSAndroid Build Coastguard Worker status_t ATSParser::setMediaCas(const sp<ICas> &cas) {
2011*ec779b8eSAndroid Build Coastguard Worker     status_t err = mCasManager->setMediaCas(cas);
2012*ec779b8eSAndroid Build Coastguard Worker     if (err != OK) {
2013*ec779b8eSAndroid Build Coastguard Worker         return err;
2014*ec779b8eSAndroid Build Coastguard Worker     }
2015*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < mPrograms.size(); ++i) {
2016*ec779b8eSAndroid Build Coastguard Worker         mPrograms.editItemAt(i)->updateCasSessions();
2017*ec779b8eSAndroid Build Coastguard Worker     }
2018*ec779b8eSAndroid Build Coastguard Worker     return OK;
2019*ec779b8eSAndroid Build Coastguard Worker }
2020*ec779b8eSAndroid Build Coastguard Worker 
signalDiscontinuity(DiscontinuityType type,const sp<AMessage> & extra)2021*ec779b8eSAndroid Build Coastguard Worker void ATSParser::signalDiscontinuity(
2022*ec779b8eSAndroid Build Coastguard Worker         DiscontinuityType type, const sp<AMessage> &extra) {
2023*ec779b8eSAndroid Build Coastguard Worker     int64_t mediaTimeUs;
2024*ec779b8eSAndroid Build Coastguard Worker     if ((type & DISCONTINUITY_TIME) && extra != NULL) {
2025*ec779b8eSAndroid Build Coastguard Worker         if (extra->findInt64(kATSParserKeyMediaTimeUs, &mediaTimeUs)) {
2026*ec779b8eSAndroid Build Coastguard Worker             mAbsoluteTimeAnchorUs = mediaTimeUs;
2027*ec779b8eSAndroid Build Coastguard Worker         }
2028*ec779b8eSAndroid Build Coastguard Worker         if ((mFlags & TS_TIMESTAMPS_ARE_ABSOLUTE)
2029*ec779b8eSAndroid Build Coastguard Worker                 && extra->findInt64(
2030*ec779b8eSAndroid Build Coastguard Worker                     kATSParserKeyRecentMediaTimeUs, &mediaTimeUs)) {
2031*ec779b8eSAndroid Build Coastguard Worker             if (mAbsoluteTimeAnchorUs >= 0LL) {
2032*ec779b8eSAndroid Build Coastguard Worker                 mediaTimeUs -= mAbsoluteTimeAnchorUs;
2033*ec779b8eSAndroid Build Coastguard Worker             }
2034*ec779b8eSAndroid Build Coastguard Worker             if (mTimeOffsetValid) {
2035*ec779b8eSAndroid Build Coastguard Worker                 mediaTimeUs -= mTimeOffsetUs;
2036*ec779b8eSAndroid Build Coastguard Worker             }
2037*ec779b8eSAndroid Build Coastguard Worker             mLastRecoveredPTS = (mediaTimeUs * 9) / 100;
2038*ec779b8eSAndroid Build Coastguard Worker         }
2039*ec779b8eSAndroid Build Coastguard Worker     } else if (type == DISCONTINUITY_ABSOLUTE_TIME) {
2040*ec779b8eSAndroid Build Coastguard Worker         int64_t timeUs;
2041*ec779b8eSAndroid Build Coastguard Worker         if (!extra->findInt64("timeUs", &timeUs)) {
2042*ec779b8eSAndroid Build Coastguard Worker             ALOGE("timeUs not found");
2043*ec779b8eSAndroid Build Coastguard Worker             return;
2044*ec779b8eSAndroid Build Coastguard Worker         }
2045*ec779b8eSAndroid Build Coastguard Worker 
2046*ec779b8eSAndroid Build Coastguard Worker         if (!mPrograms.empty()) {
2047*ec779b8eSAndroid Build Coastguard Worker             ALOGE("mPrograms is not empty");
2048*ec779b8eSAndroid Build Coastguard Worker             return;
2049*ec779b8eSAndroid Build Coastguard Worker         }
2050*ec779b8eSAndroid Build Coastguard Worker         mAbsoluteTimeAnchorUs = timeUs;
2051*ec779b8eSAndroid Build Coastguard Worker         return;
2052*ec779b8eSAndroid Build Coastguard Worker     } else if (type == DISCONTINUITY_TIME_OFFSET) {
2053*ec779b8eSAndroid Build Coastguard Worker         int64_t offset;
2054*ec779b8eSAndroid Build Coastguard Worker         if (!extra->findInt64("offset", &offset)) {
2055*ec779b8eSAndroid Build Coastguard Worker             ALOGE("offset not found");
2056*ec779b8eSAndroid Build Coastguard Worker             return;
2057*ec779b8eSAndroid Build Coastguard Worker         }
2058*ec779b8eSAndroid Build Coastguard Worker 
2059*ec779b8eSAndroid Build Coastguard Worker         mTimeOffsetValid = true;
2060*ec779b8eSAndroid Build Coastguard Worker         mTimeOffsetUs = offset;
2061*ec779b8eSAndroid Build Coastguard Worker         return;
2062*ec779b8eSAndroid Build Coastguard Worker     }
2063*ec779b8eSAndroid Build Coastguard Worker 
2064*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < mPrograms.size(); ++i) {
2065*ec779b8eSAndroid Build Coastguard Worker         mPrograms.editItemAt(i)->signalDiscontinuity(type, extra);
2066*ec779b8eSAndroid Build Coastguard Worker     }
2067*ec779b8eSAndroid Build Coastguard Worker }
2068*ec779b8eSAndroid Build Coastguard Worker 
signalEOS(status_t finalResult)2069*ec779b8eSAndroid Build Coastguard Worker void ATSParser::signalEOS(status_t finalResult) {
2070*ec779b8eSAndroid Build Coastguard Worker     if (finalResult == (status_t) OK) {
2071*ec779b8eSAndroid Build Coastguard Worker         ALOGE("finalResult not OK");
2072*ec779b8eSAndroid Build Coastguard Worker         return;
2073*ec779b8eSAndroid Build Coastguard Worker     }
2074*ec779b8eSAndroid Build Coastguard Worker 
2075*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < mPrograms.size(); ++i) {
2076*ec779b8eSAndroid Build Coastguard Worker         mPrograms.editItemAt(i)->signalEOS(finalResult);
2077*ec779b8eSAndroid Build Coastguard Worker     }
2078*ec779b8eSAndroid Build Coastguard Worker }
2079*ec779b8eSAndroid Build Coastguard Worker 
parseProgramAssociationTable(ABitReader * br)2080*ec779b8eSAndroid Build Coastguard Worker void ATSParser::parseProgramAssociationTable(ABitReader *br) {
2081*ec779b8eSAndroid Build Coastguard Worker     if (br->numBitsLeft() < 8) {
2082*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Not enough data left in bitreader!");
2083*ec779b8eSAndroid Build Coastguard Worker         return;
2084*ec779b8eSAndroid Build Coastguard Worker     }
2085*ec779b8eSAndroid Build Coastguard Worker     unsigned table_id = br->getBits(8);
2086*ec779b8eSAndroid Build Coastguard Worker     ALOGV("  table_id = %u", table_id);
2087*ec779b8eSAndroid Build Coastguard Worker     if (table_id != 0x00u) {
2088*ec779b8eSAndroid Build Coastguard Worker         ALOGE("PAT data error!");
2089*ec779b8eSAndroid Build Coastguard Worker         return ;
2090*ec779b8eSAndroid Build Coastguard Worker     }
2091*ec779b8eSAndroid Build Coastguard Worker     if (br->numBitsLeft() < 56) {
2092*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Not enough data left in bitreader!");
2093*ec779b8eSAndroid Build Coastguard Worker         return;
2094*ec779b8eSAndroid Build Coastguard Worker     }
2095*ec779b8eSAndroid Build Coastguard Worker     unsigned section_syntax_indictor = br->getBits(1);
2096*ec779b8eSAndroid Build Coastguard Worker     ALOGV("  section_syntax_indictor = %u", section_syntax_indictor);
2097*ec779b8eSAndroid Build Coastguard Worker 
2098*ec779b8eSAndroid Build Coastguard Worker     br->skipBits(1);  // '0'
2099*ec779b8eSAndroid Build Coastguard Worker     MY_LOGV("  reserved = %u", br->getBits(2));
2100*ec779b8eSAndroid Build Coastguard Worker 
2101*ec779b8eSAndroid Build Coastguard Worker     unsigned section_length = br->getBits(12);
2102*ec779b8eSAndroid Build Coastguard Worker     ALOGV("  section_length = %u", section_length);
2103*ec779b8eSAndroid Build Coastguard Worker 
2104*ec779b8eSAndroid Build Coastguard Worker     MY_LOGV("  transport_stream_id = %u", br->getBits(16));
2105*ec779b8eSAndroid Build Coastguard Worker     MY_LOGV("  reserved = %u", br->getBits(2));
2106*ec779b8eSAndroid Build Coastguard Worker     MY_LOGV("  version_number = %u", br->getBits(5));
2107*ec779b8eSAndroid Build Coastguard Worker     MY_LOGV("  current_next_indicator = %u", br->getBits(1));
2108*ec779b8eSAndroid Build Coastguard Worker     MY_LOGV("  section_number = %u", br->getBits(8));
2109*ec779b8eSAndroid Build Coastguard Worker     MY_LOGV("  last_section_number = %u", br->getBits(8));
2110*ec779b8eSAndroid Build Coastguard Worker 
2111*ec779b8eSAndroid Build Coastguard Worker     // check for unsigned integer overflow before assigning it to numProgramBytes
2112*ec779b8eSAndroid Build Coastguard Worker     if (section_length < 9) {
2113*ec779b8eSAndroid Build Coastguard Worker         return;
2114*ec779b8eSAndroid Build Coastguard Worker     }
2115*ec779b8eSAndroid Build Coastguard Worker     size_t numProgramBytes = (section_length - 5 /* header */ - 4 /* crc */);
2116*ec779b8eSAndroid Build Coastguard Worker 
2117*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < numProgramBytes / 4; ++i) {
2118*ec779b8eSAndroid Build Coastguard Worker         if (br->numBitsLeft() < 32) {
2119*ec779b8eSAndroid Build Coastguard Worker             ALOGE("Not enough data left in bitreader!");
2120*ec779b8eSAndroid Build Coastguard Worker             return;
2121*ec779b8eSAndroid Build Coastguard Worker         }
2122*ec779b8eSAndroid Build Coastguard Worker         unsigned program_number = br->getBits(16);
2123*ec779b8eSAndroid Build Coastguard Worker         ALOGV("    program_number = %u", program_number);
2124*ec779b8eSAndroid Build Coastguard Worker 
2125*ec779b8eSAndroid Build Coastguard Worker         MY_LOGV("    reserved = %u", br->getBits(3));
2126*ec779b8eSAndroid Build Coastguard Worker 
2127*ec779b8eSAndroid Build Coastguard Worker         if (program_number == 0) {
2128*ec779b8eSAndroid Build Coastguard Worker             MY_LOGV("    network_PID = 0x%04x", br->getBits(13));
2129*ec779b8eSAndroid Build Coastguard Worker         } else {
2130*ec779b8eSAndroid Build Coastguard Worker             unsigned programMapPID = br->getBits(13);
2131*ec779b8eSAndroid Build Coastguard Worker 
2132*ec779b8eSAndroid Build Coastguard Worker             ALOGV("    program_map_PID = 0x%04x", programMapPID);
2133*ec779b8eSAndroid Build Coastguard Worker 
2134*ec779b8eSAndroid Build Coastguard Worker             bool found = false;
2135*ec779b8eSAndroid Build Coastguard Worker             for (size_t index = 0; index < mPrograms.size(); ++index) {
2136*ec779b8eSAndroid Build Coastguard Worker                 const sp<Program> &program = mPrograms.itemAt(index);
2137*ec779b8eSAndroid Build Coastguard Worker 
2138*ec779b8eSAndroid Build Coastguard Worker                 if (program->number() == program_number) {
2139*ec779b8eSAndroid Build Coastguard Worker                     program->updateProgramMapPID(programMapPID);
2140*ec779b8eSAndroid Build Coastguard Worker                     found = true;
2141*ec779b8eSAndroid Build Coastguard Worker                     break;
2142*ec779b8eSAndroid Build Coastguard Worker                 }
2143*ec779b8eSAndroid Build Coastguard Worker             }
2144*ec779b8eSAndroid Build Coastguard Worker 
2145*ec779b8eSAndroid Build Coastguard Worker             if (!found) {
2146*ec779b8eSAndroid Build Coastguard Worker                 mPrograms.push(
2147*ec779b8eSAndroid Build Coastguard Worker                         new Program(this, program_number, programMapPID, mLastRecoveredPTS));
2148*ec779b8eSAndroid Build Coastguard Worker                 if (mSampleAesKeyItem != NULL) {
2149*ec779b8eSAndroid Build Coastguard Worker                     mPrograms.top()->signalNewSampleAesKey(mSampleAesKeyItem);
2150*ec779b8eSAndroid Build Coastguard Worker                 }
2151*ec779b8eSAndroid Build Coastguard Worker             }
2152*ec779b8eSAndroid Build Coastguard Worker 
2153*ec779b8eSAndroid Build Coastguard Worker             if (mPSISections.indexOfKey(programMapPID) < 0) {
2154*ec779b8eSAndroid Build Coastguard Worker                 mPSISections.add(programMapPID, new PSISection);
2155*ec779b8eSAndroid Build Coastguard Worker             }
2156*ec779b8eSAndroid Build Coastguard Worker         }
2157*ec779b8eSAndroid Build Coastguard Worker     }
2158*ec779b8eSAndroid Build Coastguard Worker 
2159*ec779b8eSAndroid Build Coastguard Worker     if (br->numBitsLeft() < 32) {
2160*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Not enough data left in bitreader!");
2161*ec779b8eSAndroid Build Coastguard Worker         return;
2162*ec779b8eSAndroid Build Coastguard Worker     }
2163*ec779b8eSAndroid Build Coastguard Worker     MY_LOGV("  CRC = 0x%08x", br->getBits(32));
2164*ec779b8eSAndroid Build Coastguard Worker }
2165*ec779b8eSAndroid Build Coastguard Worker 
parsePID(ABitReader * br,unsigned PID,unsigned continuity_counter,unsigned payload_unit_start_indicator,unsigned transport_scrambling_control,unsigned random_access_indicator,SyncEvent * event)2166*ec779b8eSAndroid Build Coastguard Worker status_t ATSParser::parsePID(
2167*ec779b8eSAndroid Build Coastguard Worker         ABitReader *br, unsigned PID,
2168*ec779b8eSAndroid Build Coastguard Worker         unsigned continuity_counter,
2169*ec779b8eSAndroid Build Coastguard Worker         unsigned payload_unit_start_indicator,
2170*ec779b8eSAndroid Build Coastguard Worker         unsigned transport_scrambling_control,
2171*ec779b8eSAndroid Build Coastguard Worker         unsigned random_access_indicator,
2172*ec779b8eSAndroid Build Coastguard Worker         SyncEvent *event) {
2173*ec779b8eSAndroid Build Coastguard Worker     ssize_t sectionIndex = mPSISections.indexOfKey(PID);
2174*ec779b8eSAndroid Build Coastguard Worker 
2175*ec779b8eSAndroid Build Coastguard Worker     if (sectionIndex >= 0) {
2176*ec779b8eSAndroid Build Coastguard Worker         sp<PSISection> section = mPSISections.valueAt(sectionIndex);
2177*ec779b8eSAndroid Build Coastguard Worker 
2178*ec779b8eSAndroid Build Coastguard Worker         if (payload_unit_start_indicator) {
2179*ec779b8eSAndroid Build Coastguard Worker             if (!section->isEmpty()) {
2180*ec779b8eSAndroid Build Coastguard Worker                 ALOGW("parsePID encounters payload_unit_start_indicator when section is not empty");
2181*ec779b8eSAndroid Build Coastguard Worker                 section->clear();
2182*ec779b8eSAndroid Build Coastguard Worker             }
2183*ec779b8eSAndroid Build Coastguard Worker 
2184*ec779b8eSAndroid Build Coastguard Worker             if (br->numBitsLeft() < 8) {
2185*ec779b8eSAndroid Build Coastguard Worker                 ALOGE("Not enough data left in bitreader!");
2186*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
2187*ec779b8eSAndroid Build Coastguard Worker             }
2188*ec779b8eSAndroid Build Coastguard Worker             unsigned skip = br->getBits(8);
2189*ec779b8eSAndroid Build Coastguard Worker             section->setSkipBytes(skip + 1);  // skip filler bytes + pointer field itself
2190*ec779b8eSAndroid Build Coastguard Worker             if (!br->skipBits(skip * 8)) {
2191*ec779b8eSAndroid Build Coastguard Worker                 ALOGE("Not enough data left in bitreader!");
2192*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
2193*ec779b8eSAndroid Build Coastguard Worker             }
2194*ec779b8eSAndroid Build Coastguard Worker         }
2195*ec779b8eSAndroid Build Coastguard Worker 
2196*ec779b8eSAndroid Build Coastguard Worker         if (br->numBitsLeft() % 8 != 0) {
2197*ec779b8eSAndroid Build Coastguard Worker             return ERROR_MALFORMED;
2198*ec779b8eSAndroid Build Coastguard Worker         }
2199*ec779b8eSAndroid Build Coastguard Worker         status_t err = section->append(br->data(), br->numBitsLeft() / 8);
2200*ec779b8eSAndroid Build Coastguard Worker 
2201*ec779b8eSAndroid Build Coastguard Worker         if (err != OK) {
2202*ec779b8eSAndroid Build Coastguard Worker             return err;
2203*ec779b8eSAndroid Build Coastguard Worker         }
2204*ec779b8eSAndroid Build Coastguard Worker 
2205*ec779b8eSAndroid Build Coastguard Worker         if (!section->isComplete()) {
2206*ec779b8eSAndroid Build Coastguard Worker             return OK;
2207*ec779b8eSAndroid Build Coastguard Worker         }
2208*ec779b8eSAndroid Build Coastguard Worker 
2209*ec779b8eSAndroid Build Coastguard Worker         if (!section->isCRCOkay()) {
2210*ec779b8eSAndroid Build Coastguard Worker             return BAD_VALUE;
2211*ec779b8eSAndroid Build Coastguard Worker         }
2212*ec779b8eSAndroid Build Coastguard Worker         ABitReader sectionBits(section->data(), section->size());
2213*ec779b8eSAndroid Build Coastguard Worker 
2214*ec779b8eSAndroid Build Coastguard Worker         if (PID == 0) {
2215*ec779b8eSAndroid Build Coastguard Worker             parseProgramAssociationTable(&sectionBits);
2216*ec779b8eSAndroid Build Coastguard Worker         } else {
2217*ec779b8eSAndroid Build Coastguard Worker             bool handled = false;
2218*ec779b8eSAndroid Build Coastguard Worker             for (size_t i = 0; i < mPrograms.size(); ++i) {
2219*ec779b8eSAndroid Build Coastguard Worker                 status_t err;
2220*ec779b8eSAndroid Build Coastguard Worker                 if (!mPrograms.editItemAt(i)->parsePSISection(
2221*ec779b8eSAndroid Build Coastguard Worker                             PID, &sectionBits, &err)) {
2222*ec779b8eSAndroid Build Coastguard Worker                     continue;
2223*ec779b8eSAndroid Build Coastguard Worker                 }
2224*ec779b8eSAndroid Build Coastguard Worker 
2225*ec779b8eSAndroid Build Coastguard Worker                 if (err != OK) {
2226*ec779b8eSAndroid Build Coastguard Worker                     return err;
2227*ec779b8eSAndroid Build Coastguard Worker                 }
2228*ec779b8eSAndroid Build Coastguard Worker 
2229*ec779b8eSAndroid Build Coastguard Worker                 handled = true;
2230*ec779b8eSAndroid Build Coastguard Worker                 break;
2231*ec779b8eSAndroid Build Coastguard Worker             }
2232*ec779b8eSAndroid Build Coastguard Worker 
2233*ec779b8eSAndroid Build Coastguard Worker             if (!handled) {
2234*ec779b8eSAndroid Build Coastguard Worker                 mPSISections.removeItem(PID);
2235*ec779b8eSAndroid Build Coastguard Worker                 section.clear();
2236*ec779b8eSAndroid Build Coastguard Worker             }
2237*ec779b8eSAndroid Build Coastguard Worker         }
2238*ec779b8eSAndroid Build Coastguard Worker 
2239*ec779b8eSAndroid Build Coastguard Worker         if (section != NULL) {
2240*ec779b8eSAndroid Build Coastguard Worker             section->clear();
2241*ec779b8eSAndroid Build Coastguard Worker         }
2242*ec779b8eSAndroid Build Coastguard Worker 
2243*ec779b8eSAndroid Build Coastguard Worker         return OK;
2244*ec779b8eSAndroid Build Coastguard Worker     }
2245*ec779b8eSAndroid Build Coastguard Worker 
2246*ec779b8eSAndroid Build Coastguard Worker     bool handled = false;
2247*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < mPrograms.size(); ++i) {
2248*ec779b8eSAndroid Build Coastguard Worker         status_t err;
2249*ec779b8eSAndroid Build Coastguard Worker         if (mPrograms.editItemAt(i)->parsePID(
2250*ec779b8eSAndroid Build Coastguard Worker                     PID, continuity_counter,
2251*ec779b8eSAndroid Build Coastguard Worker                     payload_unit_start_indicator,
2252*ec779b8eSAndroid Build Coastguard Worker                     transport_scrambling_control,
2253*ec779b8eSAndroid Build Coastguard Worker                     random_access_indicator,
2254*ec779b8eSAndroid Build Coastguard Worker                     br, &err, event)) {
2255*ec779b8eSAndroid Build Coastguard Worker             if (err != OK) {
2256*ec779b8eSAndroid Build Coastguard Worker                 return err;
2257*ec779b8eSAndroid Build Coastguard Worker             }
2258*ec779b8eSAndroid Build Coastguard Worker 
2259*ec779b8eSAndroid Build Coastguard Worker             handled = true;
2260*ec779b8eSAndroid Build Coastguard Worker             break;
2261*ec779b8eSAndroid Build Coastguard Worker         }
2262*ec779b8eSAndroid Build Coastguard Worker     }
2263*ec779b8eSAndroid Build Coastguard Worker 
2264*ec779b8eSAndroid Build Coastguard Worker     if (!handled) {
2265*ec779b8eSAndroid Build Coastguard Worker         handled = mCasManager->parsePID(br, PID);
2266*ec779b8eSAndroid Build Coastguard Worker     }
2267*ec779b8eSAndroid Build Coastguard Worker 
2268*ec779b8eSAndroid Build Coastguard Worker     if (!handled) {
2269*ec779b8eSAndroid Build Coastguard Worker         ALOGV("PID 0x%04x not handled.", PID);
2270*ec779b8eSAndroid Build Coastguard Worker     }
2271*ec779b8eSAndroid Build Coastguard Worker 
2272*ec779b8eSAndroid Build Coastguard Worker     return OK;
2273*ec779b8eSAndroid Build Coastguard Worker }
2274*ec779b8eSAndroid Build Coastguard Worker 
parseAdaptationField(ABitReader * br,unsigned PID,unsigned * random_access_indicator)2275*ec779b8eSAndroid Build Coastguard Worker status_t ATSParser::parseAdaptationField(
2276*ec779b8eSAndroid Build Coastguard Worker         ABitReader *br, unsigned PID, unsigned *random_access_indicator) {
2277*ec779b8eSAndroid Build Coastguard Worker     *random_access_indicator = 0;
2278*ec779b8eSAndroid Build Coastguard Worker     if (br->numBitsLeft() < 8) {
2279*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Not enough data left in bitreader!");
2280*ec779b8eSAndroid Build Coastguard Worker         return ERROR_MALFORMED;
2281*ec779b8eSAndroid Build Coastguard Worker     }
2282*ec779b8eSAndroid Build Coastguard Worker     unsigned adaptation_field_length = br->getBits(8);
2283*ec779b8eSAndroid Build Coastguard Worker 
2284*ec779b8eSAndroid Build Coastguard Worker     if (adaptation_field_length > 0) {
2285*ec779b8eSAndroid Build Coastguard Worker         if (adaptation_field_length * 8 > br->numBitsLeft()) {
2286*ec779b8eSAndroid Build Coastguard Worker             ALOGV("Adaptation field should be included in a single TS packet.");
2287*ec779b8eSAndroid Build Coastguard Worker             return ERROR_MALFORMED;
2288*ec779b8eSAndroid Build Coastguard Worker         }
2289*ec779b8eSAndroid Build Coastguard Worker 
2290*ec779b8eSAndroid Build Coastguard Worker         unsigned discontinuity_indicator = br->getBits(1);
2291*ec779b8eSAndroid Build Coastguard Worker 
2292*ec779b8eSAndroid Build Coastguard Worker         if (discontinuity_indicator) {
2293*ec779b8eSAndroid Build Coastguard Worker             ALOGV("PID 0x%04x: discontinuity_indicator = 1 (!!!)", PID);
2294*ec779b8eSAndroid Build Coastguard Worker         }
2295*ec779b8eSAndroid Build Coastguard Worker 
2296*ec779b8eSAndroid Build Coastguard Worker         *random_access_indicator = br->getBits(1);
2297*ec779b8eSAndroid Build Coastguard Worker         if (*random_access_indicator) {
2298*ec779b8eSAndroid Build Coastguard Worker             ALOGV("PID 0x%04x: random_access_indicator = 1", PID);
2299*ec779b8eSAndroid Build Coastguard Worker         }
2300*ec779b8eSAndroid Build Coastguard Worker 
2301*ec779b8eSAndroid Build Coastguard Worker         unsigned elementary_stream_priority_indicator = br->getBits(1);
2302*ec779b8eSAndroid Build Coastguard Worker         if (elementary_stream_priority_indicator) {
2303*ec779b8eSAndroid Build Coastguard Worker             ALOGV("PID 0x%04x: elementary_stream_priority_indicator = 1", PID);
2304*ec779b8eSAndroid Build Coastguard Worker         }
2305*ec779b8eSAndroid Build Coastguard Worker 
2306*ec779b8eSAndroid Build Coastguard Worker         unsigned PCR_flag = br->getBits(1);
2307*ec779b8eSAndroid Build Coastguard Worker 
2308*ec779b8eSAndroid Build Coastguard Worker         size_t numBitsRead = 4;
2309*ec779b8eSAndroid Build Coastguard Worker 
2310*ec779b8eSAndroid Build Coastguard Worker         if (PCR_flag) {
2311*ec779b8eSAndroid Build Coastguard Worker             if (adaptation_field_length * 8 < 52) {
2312*ec779b8eSAndroid Build Coastguard Worker                 return ERROR_MALFORMED;
2313*ec779b8eSAndroid Build Coastguard Worker             }
2314*ec779b8eSAndroid Build Coastguard Worker             br->skipBits(4);
2315*ec779b8eSAndroid Build Coastguard Worker             uint64_t PCR_base = br->getBits(32);
2316*ec779b8eSAndroid Build Coastguard Worker             PCR_base = (PCR_base << 1) | br->getBits(1);
2317*ec779b8eSAndroid Build Coastguard Worker 
2318*ec779b8eSAndroid Build Coastguard Worker             br->skipBits(6);
2319*ec779b8eSAndroid Build Coastguard Worker             unsigned PCR_ext = br->getBits(9);
2320*ec779b8eSAndroid Build Coastguard Worker 
2321*ec779b8eSAndroid Build Coastguard Worker             // The number of bytes from the start of the current
2322*ec779b8eSAndroid Build Coastguard Worker             // MPEG2 transport stream packet up and including
2323*ec779b8eSAndroid Build Coastguard Worker             // the final byte of this PCR_ext field.
2324*ec779b8eSAndroid Build Coastguard Worker             size_t byteOffsetFromStartOfTSPacket =
2325*ec779b8eSAndroid Build Coastguard Worker                 (188 - br->numBitsLeft() / 8);
2326*ec779b8eSAndroid Build Coastguard Worker 
2327*ec779b8eSAndroid Build Coastguard Worker             uint64_t PCR = PCR_base * 300 + PCR_ext;
2328*ec779b8eSAndroid Build Coastguard Worker 
2329*ec779b8eSAndroid Build Coastguard Worker             ALOGV("PID 0x%04x: PCR = 0x%016" PRIx64 " (%.2f)",
2330*ec779b8eSAndroid Build Coastguard Worker                   PID, PCR, PCR / 27E6);
2331*ec779b8eSAndroid Build Coastguard Worker 
2332*ec779b8eSAndroid Build Coastguard Worker             // The number of bytes received by this parser up to and
2333*ec779b8eSAndroid Build Coastguard Worker             // including the final byte of this PCR_ext field.
2334*ec779b8eSAndroid Build Coastguard Worker             uint64_t byteOffsetFromStart =
2335*ec779b8eSAndroid Build Coastguard Worker                 uint64_t(mNumTSPacketsParsed) * 188 + byteOffsetFromStartOfTSPacket;
2336*ec779b8eSAndroid Build Coastguard Worker 
2337*ec779b8eSAndroid Build Coastguard Worker             for (size_t i = 0; i < mPrograms.size(); ++i) {
2338*ec779b8eSAndroid Build Coastguard Worker                 updatePCR(PID, PCR, byteOffsetFromStart);
2339*ec779b8eSAndroid Build Coastguard Worker             }
2340*ec779b8eSAndroid Build Coastguard Worker 
2341*ec779b8eSAndroid Build Coastguard Worker             numBitsRead += 52;
2342*ec779b8eSAndroid Build Coastguard Worker         }
2343*ec779b8eSAndroid Build Coastguard Worker 
2344*ec779b8eSAndroid Build Coastguard Worker         br->skipBits(adaptation_field_length * 8 - numBitsRead);
2345*ec779b8eSAndroid Build Coastguard Worker     }
2346*ec779b8eSAndroid Build Coastguard Worker     return OK;
2347*ec779b8eSAndroid Build Coastguard Worker }
2348*ec779b8eSAndroid Build Coastguard Worker 
parseTS(ABitReader * br,SyncEvent * event)2349*ec779b8eSAndroid Build Coastguard Worker status_t ATSParser::parseTS(ABitReader *br, SyncEvent *event) {
2350*ec779b8eSAndroid Build Coastguard Worker     ALOGV("---");
2351*ec779b8eSAndroid Build Coastguard Worker 
2352*ec779b8eSAndroid Build Coastguard Worker     if (br->numBitsLeft() < 32) {
2353*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Not enough data left in bitreader!");
2354*ec779b8eSAndroid Build Coastguard Worker         return ERROR_MALFORMED;
2355*ec779b8eSAndroid Build Coastguard Worker     }
2356*ec779b8eSAndroid Build Coastguard Worker     unsigned sync_byte = br->getBits(8);
2357*ec779b8eSAndroid Build Coastguard Worker     if (sync_byte != 0x47u) {
2358*ec779b8eSAndroid Build Coastguard Worker         ALOGE("[error] parseTS: return error as sync_byte=0x%x", sync_byte);
2359*ec779b8eSAndroid Build Coastguard Worker         return BAD_VALUE;
2360*ec779b8eSAndroid Build Coastguard Worker     }
2361*ec779b8eSAndroid Build Coastguard Worker 
2362*ec779b8eSAndroid Build Coastguard Worker     if (br->getBits(1)) {  // transport_error_indicator
2363*ec779b8eSAndroid Build Coastguard Worker         // silently ignore.
2364*ec779b8eSAndroid Build Coastguard Worker         return OK;
2365*ec779b8eSAndroid Build Coastguard Worker     }
2366*ec779b8eSAndroid Build Coastguard Worker 
2367*ec779b8eSAndroid Build Coastguard Worker     unsigned payload_unit_start_indicator = br->getBits(1);
2368*ec779b8eSAndroid Build Coastguard Worker     ALOGV("payload_unit_start_indicator = %u", payload_unit_start_indicator);
2369*ec779b8eSAndroid Build Coastguard Worker 
2370*ec779b8eSAndroid Build Coastguard Worker     MY_LOGV("transport_priority = %u", br->getBits(1));
2371*ec779b8eSAndroid Build Coastguard Worker 
2372*ec779b8eSAndroid Build Coastguard Worker     unsigned PID = br->getBits(13);
2373*ec779b8eSAndroid Build Coastguard Worker     ALOGV("PID = 0x%04x", PID);
2374*ec779b8eSAndroid Build Coastguard Worker 
2375*ec779b8eSAndroid Build Coastguard Worker     unsigned transport_scrambling_control = br->getBits(2);
2376*ec779b8eSAndroid Build Coastguard Worker     ALOGV("transport_scrambling_control = %u", transport_scrambling_control);
2377*ec779b8eSAndroid Build Coastguard Worker 
2378*ec779b8eSAndroid Build Coastguard Worker     unsigned adaptation_field_control = br->getBits(2);
2379*ec779b8eSAndroid Build Coastguard Worker     ALOGV("adaptation_field_control = %u", adaptation_field_control);
2380*ec779b8eSAndroid Build Coastguard Worker 
2381*ec779b8eSAndroid Build Coastguard Worker     unsigned continuity_counter = br->getBits(4);
2382*ec779b8eSAndroid Build Coastguard Worker     ALOGV("PID = 0x%04x, continuity_counter = %u", PID, continuity_counter);
2383*ec779b8eSAndroid Build Coastguard Worker 
2384*ec779b8eSAndroid Build Coastguard Worker     // ALOGI("PID = 0x%04x, continuity_counter = %u", PID, continuity_counter);
2385*ec779b8eSAndroid Build Coastguard Worker 
2386*ec779b8eSAndroid Build Coastguard Worker     status_t err = OK;
2387*ec779b8eSAndroid Build Coastguard Worker 
2388*ec779b8eSAndroid Build Coastguard Worker     unsigned random_access_indicator = 0;
2389*ec779b8eSAndroid Build Coastguard Worker     if (adaptation_field_control == 2 || adaptation_field_control == 3) {
2390*ec779b8eSAndroid Build Coastguard Worker         err = parseAdaptationField(br, PID, &random_access_indicator);
2391*ec779b8eSAndroid Build Coastguard Worker     }
2392*ec779b8eSAndroid Build Coastguard Worker     if (err == OK) {
2393*ec779b8eSAndroid Build Coastguard Worker         if (adaptation_field_control == 1 || adaptation_field_control == 3) {
2394*ec779b8eSAndroid Build Coastguard Worker             err = parsePID(br, PID, continuity_counter,
2395*ec779b8eSAndroid Build Coastguard Worker                     payload_unit_start_indicator,
2396*ec779b8eSAndroid Build Coastguard Worker                     transport_scrambling_control,
2397*ec779b8eSAndroid Build Coastguard Worker                     random_access_indicator,
2398*ec779b8eSAndroid Build Coastguard Worker                     event);
2399*ec779b8eSAndroid Build Coastguard Worker         }
2400*ec779b8eSAndroid Build Coastguard Worker     }
2401*ec779b8eSAndroid Build Coastguard Worker 
2402*ec779b8eSAndroid Build Coastguard Worker     ++mNumTSPacketsParsed;
2403*ec779b8eSAndroid Build Coastguard Worker 
2404*ec779b8eSAndroid Build Coastguard Worker     return err;
2405*ec779b8eSAndroid Build Coastguard Worker }
2406*ec779b8eSAndroid Build Coastguard Worker 
getSource(SourceType type)2407*ec779b8eSAndroid Build Coastguard Worker sp<AnotherPacketSource> ATSParser::getSource(SourceType type) {
2408*ec779b8eSAndroid Build Coastguard Worker     sp<AnotherPacketSource> firstSourceFound;
2409*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < mPrograms.size(); ++i) {
2410*ec779b8eSAndroid Build Coastguard Worker         const sp<Program> &program = mPrograms.editItemAt(i);
2411*ec779b8eSAndroid Build Coastguard Worker         sp<AnotherPacketSource> source = program->getSource(type);
2412*ec779b8eSAndroid Build Coastguard Worker         if (source == NULL) {
2413*ec779b8eSAndroid Build Coastguard Worker             continue;
2414*ec779b8eSAndroid Build Coastguard Worker         }
2415*ec779b8eSAndroid Build Coastguard Worker         if (firstSourceFound == NULL) {
2416*ec779b8eSAndroid Build Coastguard Worker             firstSourceFound = source;
2417*ec779b8eSAndroid Build Coastguard Worker         }
2418*ec779b8eSAndroid Build Coastguard Worker         // Prefer programs with both audio/video
2419*ec779b8eSAndroid Build Coastguard Worker         switch (type) {
2420*ec779b8eSAndroid Build Coastguard Worker             case VIDEO: {
2421*ec779b8eSAndroid Build Coastguard Worker                 if (program->hasSource(AUDIO)) {
2422*ec779b8eSAndroid Build Coastguard Worker                     return source;
2423*ec779b8eSAndroid Build Coastguard Worker                 }
2424*ec779b8eSAndroid Build Coastguard Worker                 break;
2425*ec779b8eSAndroid Build Coastguard Worker             }
2426*ec779b8eSAndroid Build Coastguard Worker 
2427*ec779b8eSAndroid Build Coastguard Worker             case AUDIO: {
2428*ec779b8eSAndroid Build Coastguard Worker                 if (program->hasSource(VIDEO)) {
2429*ec779b8eSAndroid Build Coastguard Worker                     return source;
2430*ec779b8eSAndroid Build Coastguard Worker                 }
2431*ec779b8eSAndroid Build Coastguard Worker                 break;
2432*ec779b8eSAndroid Build Coastguard Worker             }
2433*ec779b8eSAndroid Build Coastguard Worker 
2434*ec779b8eSAndroid Build Coastguard Worker             default:
2435*ec779b8eSAndroid Build Coastguard Worker                 return source;
2436*ec779b8eSAndroid Build Coastguard Worker         }
2437*ec779b8eSAndroid Build Coastguard Worker     }
2438*ec779b8eSAndroid Build Coastguard Worker 
2439*ec779b8eSAndroid Build Coastguard Worker     return firstSourceFound;
2440*ec779b8eSAndroid Build Coastguard Worker }
2441*ec779b8eSAndroid Build Coastguard Worker 
hasSource(SourceType type) const2442*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::hasSource(SourceType type) const {
2443*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < mPrograms.size(); ++i) {
2444*ec779b8eSAndroid Build Coastguard Worker         const sp<Program> &program = mPrograms.itemAt(i);
2445*ec779b8eSAndroid Build Coastguard Worker         if (program->hasSource(type)) {
2446*ec779b8eSAndroid Build Coastguard Worker             return true;
2447*ec779b8eSAndroid Build Coastguard Worker         }
2448*ec779b8eSAndroid Build Coastguard Worker     }
2449*ec779b8eSAndroid Build Coastguard Worker 
2450*ec779b8eSAndroid Build Coastguard Worker     return false;
2451*ec779b8eSAndroid Build Coastguard Worker }
2452*ec779b8eSAndroid Build Coastguard Worker 
PTSTimeDeltaEstablished()2453*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::PTSTimeDeltaEstablished() {
2454*ec779b8eSAndroid Build Coastguard Worker     if (mPrograms.isEmpty()) {
2455*ec779b8eSAndroid Build Coastguard Worker         return false;
2456*ec779b8eSAndroid Build Coastguard Worker     }
2457*ec779b8eSAndroid Build Coastguard Worker 
2458*ec779b8eSAndroid Build Coastguard Worker     return mPrograms.editItemAt(0)->PTSTimeDeltaEstablished();
2459*ec779b8eSAndroid Build Coastguard Worker }
2460*ec779b8eSAndroid Build Coastguard Worker 
getFirstPTSTimeUs()2461*ec779b8eSAndroid Build Coastguard Worker int64_t ATSParser::getFirstPTSTimeUs() {
2462*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < mPrograms.size(); ++i) {
2463*ec779b8eSAndroid Build Coastguard Worker         sp<ATSParser::Program> program = mPrograms.itemAt(i);
2464*ec779b8eSAndroid Build Coastguard Worker         if (program->PTSTimeDeltaEstablished()) {
2465*ec779b8eSAndroid Build Coastguard Worker             return (program->firstPTS() * 100) / 9;
2466*ec779b8eSAndroid Build Coastguard Worker         }
2467*ec779b8eSAndroid Build Coastguard Worker     }
2468*ec779b8eSAndroid Build Coastguard Worker     return -1;
2469*ec779b8eSAndroid Build Coastguard Worker }
2470*ec779b8eSAndroid Build Coastguard Worker 
2471*ec779b8eSAndroid Build Coastguard Worker __attribute__((no_sanitize("integer")))
updatePCR(unsigned,uint64_t PCR,uint64_t byteOffsetFromStart)2472*ec779b8eSAndroid Build Coastguard Worker void ATSParser::updatePCR(
2473*ec779b8eSAndroid Build Coastguard Worker         unsigned /* PID */, uint64_t PCR, uint64_t byteOffsetFromStart) {
2474*ec779b8eSAndroid Build Coastguard Worker     ALOGV("PCR 0x%016" PRIx64 " @ %" PRIx64, PCR, byteOffsetFromStart);
2475*ec779b8eSAndroid Build Coastguard Worker 
2476*ec779b8eSAndroid Build Coastguard Worker     if (mNumPCRs == 2) {
2477*ec779b8eSAndroid Build Coastguard Worker         mPCR[0] = mPCR[1];
2478*ec779b8eSAndroid Build Coastguard Worker         mPCRBytes[0] = mPCRBytes[1];
2479*ec779b8eSAndroid Build Coastguard Worker         mSystemTimeUs[0] = mSystemTimeUs[1];
2480*ec779b8eSAndroid Build Coastguard Worker         mNumPCRs = 1;
2481*ec779b8eSAndroid Build Coastguard Worker     }
2482*ec779b8eSAndroid Build Coastguard Worker 
2483*ec779b8eSAndroid Build Coastguard Worker     mPCR[mNumPCRs] = PCR;
2484*ec779b8eSAndroid Build Coastguard Worker     mPCRBytes[mNumPCRs] = byteOffsetFromStart;
2485*ec779b8eSAndroid Build Coastguard Worker     mSystemTimeUs[mNumPCRs] = ALooper::GetNowUs();
2486*ec779b8eSAndroid Build Coastguard Worker 
2487*ec779b8eSAndroid Build Coastguard Worker     ++mNumPCRs;
2488*ec779b8eSAndroid Build Coastguard Worker 
2489*ec779b8eSAndroid Build Coastguard Worker     if (mNumPCRs == 2) {
2490*ec779b8eSAndroid Build Coastguard Worker         /* Unsigned overflow here */
2491*ec779b8eSAndroid Build Coastguard Worker         double transportRate =
2492*ec779b8eSAndroid Build Coastguard Worker             (mPCRBytes[1] - mPCRBytes[0]) * 27E6 / (mPCR[1] - mPCR[0]);
2493*ec779b8eSAndroid Build Coastguard Worker 
2494*ec779b8eSAndroid Build Coastguard Worker         ALOGV("transportRate = %.2f bytes/sec", transportRate);
2495*ec779b8eSAndroid Build Coastguard Worker     }
2496*ec779b8eSAndroid Build Coastguard Worker }
2497*ec779b8eSAndroid Build Coastguard Worker 
2498*ec779b8eSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
2499*ec779b8eSAndroid Build Coastguard Worker 
2500*ec779b8eSAndroid Build Coastguard Worker 
2501*ec779b8eSAndroid Build Coastguard Worker // CRC32 used for PSI section. The table was generated by following command:
2502*ec779b8eSAndroid Build Coastguard Worker // $ python pycrc.py --model crc-32-mpeg --algorithm table-driven --generate c
2503*ec779b8eSAndroid Build Coastguard Worker // Visit http://www.tty1.net/pycrc/index_en.html for more details.
2504*ec779b8eSAndroid Build Coastguard Worker uint32_t ATSParser::PSISection::CRC_TABLE[] = {
2505*ec779b8eSAndroid Build Coastguard Worker     0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
2506*ec779b8eSAndroid Build Coastguard Worker     0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
2507*ec779b8eSAndroid Build Coastguard Worker     0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
2508*ec779b8eSAndroid Build Coastguard Worker     0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
2509*ec779b8eSAndroid Build Coastguard Worker     0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
2510*ec779b8eSAndroid Build Coastguard Worker     0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
2511*ec779b8eSAndroid Build Coastguard Worker     0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
2512*ec779b8eSAndroid Build Coastguard Worker     0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
2513*ec779b8eSAndroid Build Coastguard Worker     0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
2514*ec779b8eSAndroid Build Coastguard Worker     0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
2515*ec779b8eSAndroid Build Coastguard Worker     0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
2516*ec779b8eSAndroid Build Coastguard Worker     0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
2517*ec779b8eSAndroid Build Coastguard Worker     0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
2518*ec779b8eSAndroid Build Coastguard Worker     0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
2519*ec779b8eSAndroid Build Coastguard Worker     0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
2520*ec779b8eSAndroid Build Coastguard Worker     0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
2521*ec779b8eSAndroid Build Coastguard Worker     0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
2522*ec779b8eSAndroid Build Coastguard Worker     0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
2523*ec779b8eSAndroid Build Coastguard Worker     0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
2524*ec779b8eSAndroid Build Coastguard Worker     0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
2525*ec779b8eSAndroid Build Coastguard Worker     0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
2526*ec779b8eSAndroid Build Coastguard Worker     0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
2527*ec779b8eSAndroid Build Coastguard Worker     0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
2528*ec779b8eSAndroid Build Coastguard Worker     0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
2529*ec779b8eSAndroid Build Coastguard Worker     0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
2530*ec779b8eSAndroid Build Coastguard Worker     0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
2531*ec779b8eSAndroid Build Coastguard Worker     0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
2532*ec779b8eSAndroid Build Coastguard Worker     0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
2533*ec779b8eSAndroid Build Coastguard Worker     0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
2534*ec779b8eSAndroid Build Coastguard Worker     0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
2535*ec779b8eSAndroid Build Coastguard Worker     0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
2536*ec779b8eSAndroid Build Coastguard Worker     0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
2537*ec779b8eSAndroid Build Coastguard Worker     0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
2538*ec779b8eSAndroid Build Coastguard Worker     0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
2539*ec779b8eSAndroid Build Coastguard Worker     0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
2540*ec779b8eSAndroid Build Coastguard Worker     0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
2541*ec779b8eSAndroid Build Coastguard Worker     0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
2542*ec779b8eSAndroid Build Coastguard Worker     0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
2543*ec779b8eSAndroid Build Coastguard Worker     0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
2544*ec779b8eSAndroid Build Coastguard Worker     0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
2545*ec779b8eSAndroid Build Coastguard Worker     0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
2546*ec779b8eSAndroid Build Coastguard Worker     0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
2547*ec779b8eSAndroid Build Coastguard Worker     0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
2548*ec779b8eSAndroid Build Coastguard Worker     0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
2549*ec779b8eSAndroid Build Coastguard Worker     0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
2550*ec779b8eSAndroid Build Coastguard Worker     0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
2551*ec779b8eSAndroid Build Coastguard Worker     0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
2552*ec779b8eSAndroid Build Coastguard Worker     0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
2553*ec779b8eSAndroid Build Coastguard Worker     0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
2554*ec779b8eSAndroid Build Coastguard Worker     0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
2555*ec779b8eSAndroid Build Coastguard Worker     0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
2556*ec779b8eSAndroid Build Coastguard Worker     0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
2557*ec779b8eSAndroid Build Coastguard Worker     0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
2558*ec779b8eSAndroid Build Coastguard Worker     0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
2559*ec779b8eSAndroid Build Coastguard Worker     0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
2560*ec779b8eSAndroid Build Coastguard Worker     0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
2561*ec779b8eSAndroid Build Coastguard Worker     0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
2562*ec779b8eSAndroid Build Coastguard Worker     0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
2563*ec779b8eSAndroid Build Coastguard Worker     0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
2564*ec779b8eSAndroid Build Coastguard Worker     0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
2565*ec779b8eSAndroid Build Coastguard Worker     0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
2566*ec779b8eSAndroid Build Coastguard Worker     0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
2567*ec779b8eSAndroid Build Coastguard Worker     0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
2568*ec779b8eSAndroid Build Coastguard Worker     0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
2569*ec779b8eSAndroid Build Coastguard Worker     };
2570*ec779b8eSAndroid Build Coastguard Worker 
PSISection()2571*ec779b8eSAndroid Build Coastguard Worker ATSParser::PSISection::PSISection() :
2572*ec779b8eSAndroid Build Coastguard Worker     mSkipBytes(0) {
2573*ec779b8eSAndroid Build Coastguard Worker }
2574*ec779b8eSAndroid Build Coastguard Worker 
~PSISection()2575*ec779b8eSAndroid Build Coastguard Worker ATSParser::PSISection::~PSISection() {
2576*ec779b8eSAndroid Build Coastguard Worker }
2577*ec779b8eSAndroid Build Coastguard Worker 
append(const void * data,size_t size)2578*ec779b8eSAndroid Build Coastguard Worker status_t ATSParser::PSISection::append(const void *data, size_t size) {
2579*ec779b8eSAndroid Build Coastguard Worker     if (mBuffer == NULL || mBuffer->size() + size > mBuffer->capacity()) {
2580*ec779b8eSAndroid Build Coastguard Worker         size_t newCapacity =
2581*ec779b8eSAndroid Build Coastguard Worker             (mBuffer == NULL) ? size : mBuffer->capacity() + size;
2582*ec779b8eSAndroid Build Coastguard Worker 
2583*ec779b8eSAndroid Build Coastguard Worker         newCapacity = (newCapacity + 1023) & ~1023;
2584*ec779b8eSAndroid Build Coastguard Worker 
2585*ec779b8eSAndroid Build Coastguard Worker         sp<ABuffer> newBuffer = new ABuffer(newCapacity);
2586*ec779b8eSAndroid Build Coastguard Worker 
2587*ec779b8eSAndroid Build Coastguard Worker         if (mBuffer != NULL) {
2588*ec779b8eSAndroid Build Coastguard Worker             memcpy(newBuffer->data(), mBuffer->data(), mBuffer->size());
2589*ec779b8eSAndroid Build Coastguard Worker             newBuffer->setRange(0, mBuffer->size());
2590*ec779b8eSAndroid Build Coastguard Worker         } else {
2591*ec779b8eSAndroid Build Coastguard Worker             newBuffer->setRange(0, 0);
2592*ec779b8eSAndroid Build Coastguard Worker         }
2593*ec779b8eSAndroid Build Coastguard Worker 
2594*ec779b8eSAndroid Build Coastguard Worker         mBuffer = newBuffer;
2595*ec779b8eSAndroid Build Coastguard Worker     }
2596*ec779b8eSAndroid Build Coastguard Worker 
2597*ec779b8eSAndroid Build Coastguard Worker     memcpy(mBuffer->data() + mBuffer->size(), data, size);
2598*ec779b8eSAndroid Build Coastguard Worker     mBuffer->setRange(0, mBuffer->size() + size);
2599*ec779b8eSAndroid Build Coastguard Worker 
2600*ec779b8eSAndroid Build Coastguard Worker     return OK;
2601*ec779b8eSAndroid Build Coastguard Worker }
2602*ec779b8eSAndroid Build Coastguard Worker 
setSkipBytes(uint8_t skip)2603*ec779b8eSAndroid Build Coastguard Worker void ATSParser::PSISection::setSkipBytes(uint8_t skip) {
2604*ec779b8eSAndroid Build Coastguard Worker     mSkipBytes = skip;
2605*ec779b8eSAndroid Build Coastguard Worker }
2606*ec779b8eSAndroid Build Coastguard Worker 
clear()2607*ec779b8eSAndroid Build Coastguard Worker void ATSParser::PSISection::clear() {
2608*ec779b8eSAndroid Build Coastguard Worker     if (mBuffer != NULL) {
2609*ec779b8eSAndroid Build Coastguard Worker         mBuffer->setRange(0, 0);
2610*ec779b8eSAndroid Build Coastguard Worker     }
2611*ec779b8eSAndroid Build Coastguard Worker     mSkipBytes = 0;
2612*ec779b8eSAndroid Build Coastguard Worker }
2613*ec779b8eSAndroid Build Coastguard Worker 
isComplete() const2614*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::PSISection::isComplete() const {
2615*ec779b8eSAndroid Build Coastguard Worker     if (mBuffer == NULL || mBuffer->size() < 3) {
2616*ec779b8eSAndroid Build Coastguard Worker         return false;
2617*ec779b8eSAndroid Build Coastguard Worker     }
2618*ec779b8eSAndroid Build Coastguard Worker 
2619*ec779b8eSAndroid Build Coastguard Worker     unsigned sectionLength = U16_AT(mBuffer->data() + 1) & 0xfff;
2620*ec779b8eSAndroid Build Coastguard Worker     return mBuffer->size() >= sectionLength + 3;
2621*ec779b8eSAndroid Build Coastguard Worker }
2622*ec779b8eSAndroid Build Coastguard Worker 
isEmpty() const2623*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::PSISection::isEmpty() const {
2624*ec779b8eSAndroid Build Coastguard Worker     return mBuffer == NULL || mBuffer->size() == 0;
2625*ec779b8eSAndroid Build Coastguard Worker }
2626*ec779b8eSAndroid Build Coastguard Worker 
data() const2627*ec779b8eSAndroid Build Coastguard Worker const uint8_t *ATSParser::PSISection::data() const {
2628*ec779b8eSAndroid Build Coastguard Worker     return mBuffer == NULL ? NULL : mBuffer->data();
2629*ec779b8eSAndroid Build Coastguard Worker }
2630*ec779b8eSAndroid Build Coastguard Worker 
size() const2631*ec779b8eSAndroid Build Coastguard Worker size_t ATSParser::PSISection::size() const {
2632*ec779b8eSAndroid Build Coastguard Worker     return mBuffer == NULL ? 0 : mBuffer->size();
2633*ec779b8eSAndroid Build Coastguard Worker }
2634*ec779b8eSAndroid Build Coastguard Worker 
isCRCOkay() const2635*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::PSISection::isCRCOkay() const {
2636*ec779b8eSAndroid Build Coastguard Worker     if (!isComplete()) {
2637*ec779b8eSAndroid Build Coastguard Worker         return false;
2638*ec779b8eSAndroid Build Coastguard Worker     }
2639*ec779b8eSAndroid Build Coastguard Worker     uint8_t* data = mBuffer->data();
2640*ec779b8eSAndroid Build Coastguard Worker 
2641*ec779b8eSAndroid Build Coastguard Worker     // Return true if section_syntax_indicator says no section follows the field section_length.
2642*ec779b8eSAndroid Build Coastguard Worker     if ((data[1] & 0x80) == 0) {
2643*ec779b8eSAndroid Build Coastguard Worker         return true;
2644*ec779b8eSAndroid Build Coastguard Worker     }
2645*ec779b8eSAndroid Build Coastguard Worker 
2646*ec779b8eSAndroid Build Coastguard Worker     unsigned sectionLength = U16_AT(data + 1) & 0xfff;
2647*ec779b8eSAndroid Build Coastguard Worker     ALOGV("sectionLength %u, skip %u", sectionLength, mSkipBytes);
2648*ec779b8eSAndroid Build Coastguard Worker 
2649*ec779b8eSAndroid Build Coastguard Worker 
2650*ec779b8eSAndroid Build Coastguard Worker     if(sectionLength < mSkipBytes) {
2651*ec779b8eSAndroid Build Coastguard Worker         ALOGE("b/28333006");
2652*ec779b8eSAndroid Build Coastguard Worker         android_errorWriteLog(0x534e4554, "28333006");
2653*ec779b8eSAndroid Build Coastguard Worker         return false;
2654*ec779b8eSAndroid Build Coastguard Worker     }
2655*ec779b8eSAndroid Build Coastguard Worker 
2656*ec779b8eSAndroid Build Coastguard Worker     // Skip the preceding field present when payload start indicator is on.
2657*ec779b8eSAndroid Build Coastguard Worker     sectionLength -= mSkipBytes;
2658*ec779b8eSAndroid Build Coastguard Worker 
2659*ec779b8eSAndroid Build Coastguard Worker     uint32_t crc = 0xffffffff;
2660*ec779b8eSAndroid Build Coastguard Worker     for(unsigned i = 0; i < sectionLength + 4 /* crc */; i++) {
2661*ec779b8eSAndroid Build Coastguard Worker         uint8_t b = data[i];
2662*ec779b8eSAndroid Build Coastguard Worker         int index = ((crc >> 24) ^ (b & 0xff)) & 0xff;
2663*ec779b8eSAndroid Build Coastguard Worker         crc = CRC_TABLE[index] ^ (crc << 8);
2664*ec779b8eSAndroid Build Coastguard Worker     }
2665*ec779b8eSAndroid Build Coastguard Worker     ALOGV("crc: %08x\n", crc);
2666*ec779b8eSAndroid Build Coastguard Worker     return (crc == 0);
2667*ec779b8eSAndroid Build Coastguard Worker }
2668*ec779b8eSAndroid Build Coastguard Worker 
2669*ec779b8eSAndroid Build Coastguard Worker // SAMPLE_AES key handling
2670*ec779b8eSAndroid Build Coastguard Worker // TODO: Merge these to their respective class after Widevine-HLS
signalNewSampleAesKey(const sp<AMessage> & keyItem)2671*ec779b8eSAndroid Build Coastguard Worker void ATSParser::signalNewSampleAesKey(const sp<AMessage> &keyItem) {
2672*ec779b8eSAndroid Build Coastguard Worker     ALOGD("signalNewSampleAesKey: %p", keyItem.get());
2673*ec779b8eSAndroid Build Coastguard Worker 
2674*ec779b8eSAndroid Build Coastguard Worker     mSampleAesKeyItem = keyItem;
2675*ec779b8eSAndroid Build Coastguard Worker 
2676*ec779b8eSAndroid Build Coastguard Worker     // a NULL key item will propagate to existing ElementaryStreamQueues
2677*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < mPrograms.size(); ++i) {
2678*ec779b8eSAndroid Build Coastguard Worker         mPrograms[i]->signalNewSampleAesKey(keyItem);
2679*ec779b8eSAndroid Build Coastguard Worker     }
2680*ec779b8eSAndroid Build Coastguard Worker }
2681*ec779b8eSAndroid Build Coastguard Worker 
signalNewSampleAesKey(const sp<AMessage> & keyItem)2682*ec779b8eSAndroid Build Coastguard Worker void ATSParser::Program::signalNewSampleAesKey(const sp<AMessage> &keyItem) {
2683*ec779b8eSAndroid Build Coastguard Worker     ALOGD("Program::signalNewSampleAesKey: %p", keyItem.get());
2684*ec779b8eSAndroid Build Coastguard Worker 
2685*ec779b8eSAndroid Build Coastguard Worker     mSampleAesKeyItem = keyItem;
2686*ec779b8eSAndroid Build Coastguard Worker 
2687*ec779b8eSAndroid Build Coastguard Worker     // a NULL key item will propagate to existing ElementaryStreamQueues
2688*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < mStreams.size(); ++i) {
2689*ec779b8eSAndroid Build Coastguard Worker         mStreams[i]->signalNewSampleAesKey(keyItem);
2690*ec779b8eSAndroid Build Coastguard Worker     }
2691*ec779b8eSAndroid Build Coastguard Worker }
2692*ec779b8eSAndroid Build Coastguard Worker 
signalNewSampleAesKey(const sp<AMessage> & keyItem)2693*ec779b8eSAndroid Build Coastguard Worker void ATSParser::Stream::signalNewSampleAesKey(const sp<AMessage> &keyItem) {
2694*ec779b8eSAndroid Build Coastguard Worker     ALOGD("Stream::signalNewSampleAesKey: 0x%04x size = %zu keyItem: %p",
2695*ec779b8eSAndroid Build Coastguard Worker           mElementaryPID, mBuffer->size(), keyItem.get());
2696*ec779b8eSAndroid Build Coastguard Worker 
2697*ec779b8eSAndroid Build Coastguard Worker     // a NULL key item will propagate to existing ElementaryStreamQueues
2698*ec779b8eSAndroid Build Coastguard Worker     mSampleAesKeyItem = keyItem;
2699*ec779b8eSAndroid Build Coastguard Worker 
2700*ec779b8eSAndroid Build Coastguard Worker     flush(NULL);
2701*ec779b8eSAndroid Build Coastguard Worker     mQueue->signalNewSampleAesKey(keyItem);
2702*ec779b8eSAndroid Build Coastguard Worker }
2703*ec779b8eSAndroid Build Coastguard Worker 
2704*ec779b8eSAndroid Build Coastguard Worker }  // namespace android
2705