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(§ionBits);
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, §ionBits, &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