OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / frameworks / base / media / libstagefright / mpeg2ts / ATSParser.cpp
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "ATSParser"
19 #include <utils/Log.h>
20
21 #include "ATSParser.h"
22
23 #include "AnotherPacketSource.h"
24 #include "ESQueue.h"
25 #include "include/avc_utils.h"
26
27 #include <media/stagefright/foundation/ABitReader.h>
28 #include <media/stagefright/foundation/ABuffer.h>
29 #include <media/stagefright/foundation/ADebug.h>
30 #include <media/stagefright/foundation/AMessage.h>
31 #include <media/stagefright/foundation/hexdump.h>
32 #include <media/stagefright/MediaDefs.h>
33 #include <media/stagefright/MediaErrors.h>
34 #include <media/stagefright/MetaData.h>
35 #include <utils/KeyedVector.h>
36
37 namespace android {
38
39 // I want the expression "y" evaluated even if verbose logging is off.
40 #define MY_LOGV(x, y) \
41     do { unsigned tmp = y; LOGV(x, tmp); } while (0)
42
43 static const size_t kTSPacketSize = 188;
44
45 struct ATSParser::Program : public RefBase {
46     Program(unsigned programMapPID);
47
48     bool parsePID(
49             unsigned pid, unsigned payload_unit_start_indicator,
50             ABitReader *br);
51
52     void signalDiscontinuity(bool isASeek);
53
54     sp<MediaSource> getSource(SourceType type);
55
56     int64_t convertPTSToTimestamp(uint64_t PTS);
57
58 private:
59     unsigned mProgramMapPID;
60     KeyedVector<unsigned, sp<Stream> > mStreams;
61     bool mFirstPTSValid;
62     uint64_t mFirstPTS;
63
64     void parseProgramMap(ABitReader *br);
65
66     DISALLOW_EVIL_CONSTRUCTORS(Program);
67 };
68
69 struct ATSParser::Stream : public RefBase {
70     Stream(Program *program, unsigned elementaryPID, unsigned streamType);
71
72     void parse(
73             unsigned payload_unit_start_indicator,
74             ABitReader *br);
75
76     void signalDiscontinuity(bool isASeek);
77
78     sp<MediaSource> getSource(SourceType type);
79
80 protected:
81     virtual ~Stream();
82
83 private:
84     Program *mProgram;
85     unsigned mElementaryPID;
86     unsigned mStreamType;
87
88     sp<ABuffer> mBuffer;
89     sp<AnotherPacketSource> mSource;
90     bool mPayloadStarted;
91
92     ElementaryStreamQueue mQueue;
93
94     void flush();
95     void parsePES(ABitReader *br);
96
97     void onPayloadData(
98             unsigned PTS_DTS_flags, uint64_t PTS, uint64_t DTS,
99             const uint8_t *data, size_t size);
100
101     void extractAACFrames(const sp<ABuffer> &buffer);
102
103     DISALLOW_EVIL_CONSTRUCTORS(Stream);
104 };
105
106 ////////////////////////////////////////////////////////////////////////////////
107
108 ATSParser::Program::Program(unsigned programMapPID)
109     : mProgramMapPID(programMapPID),
110       mFirstPTSValid(false),
111       mFirstPTS(0) {
112 }
113
114 bool ATSParser::Program::parsePID(
115         unsigned pid, unsigned payload_unit_start_indicator,
116         ABitReader *br) {
117     if (pid == mProgramMapPID) {
118         if (payload_unit_start_indicator) {
119             unsigned skip = br->getBits(8);
120             br->skipBits(skip * 8);
121         }
122
123         parseProgramMap(br);
124         return true;
125     }
126
127     ssize_t index = mStreams.indexOfKey(pid);
128     if (index < 0) {
129         return false;
130     }
131
132     mStreams.editValueAt(index)->parse(
133             payload_unit_start_indicator, br);
134
135     return true;
136 }
137
138 void ATSParser::Program::signalDiscontinuity(bool isASeek) {
139     for (size_t i = 0; i < mStreams.size(); ++i) {
140         mStreams.editValueAt(i)->signalDiscontinuity(isASeek);
141     }
142 }
143
144 void ATSParser::Program::parseProgramMap(ABitReader *br) {
145     unsigned table_id = br->getBits(8);
146     LOGV("  table_id = %u", table_id);
147     CHECK_EQ(table_id, 0x02u);
148
149     unsigned section_syntax_indicator = br->getBits(1);
150     LOGV("  section_syntax_indicator = %u", section_syntax_indicator);
151     CHECK_EQ(section_syntax_indicator, 1u);
152
153     CHECK_EQ(br->getBits(1), 0u);
154     MY_LOGV("  reserved = %u", br->getBits(2));
155
156     unsigned section_length = br->getBits(12);
157     LOGV("  section_length = %u", section_length);
158     CHECK((section_length & 0xc00) == 0);
159     CHECK_LE(section_length, 1021u);
160
161     MY_LOGV("  program_number = %u", br->getBits(16));
162     MY_LOGV("  reserved = %u", br->getBits(2));
163     MY_LOGV("  version_number = %u", br->getBits(5));
164     MY_LOGV("  current_next_indicator = %u", br->getBits(1));
165     MY_LOGV("  section_number = %u", br->getBits(8));
166     MY_LOGV("  last_section_number = %u", br->getBits(8));
167     MY_LOGV("  reserved = %u", br->getBits(3));
168     MY_LOGV("  PCR_PID = 0x%04x", br->getBits(13));
169     MY_LOGV("  reserved = %u", br->getBits(4));
170
171     unsigned program_info_length = br->getBits(12);
172     LOGV("  program_info_length = %u", program_info_length);
173     CHECK((program_info_length & 0xc00) == 0);
174
175     br->skipBits(program_info_length * 8);  // skip descriptors
176
177     // infoBytesRemaining is the number of bytes that make up the
178     // variable length section of ES_infos. It does not include the
179     // final CRC.
180     size_t infoBytesRemaining = section_length - 9 - program_info_length - 4;
181
182     while (infoBytesRemaining > 0) {
183         CHECK_GE(infoBytesRemaining, 5u);
184
185         unsigned streamType = br->getBits(8);
186         LOGV("    stream_type = 0x%02x", streamType);
187
188         MY_LOGV("    reserved = %u", br->getBits(3));
189
190         unsigned elementaryPID = br->getBits(13);
191         LOGV("    elementary_PID = 0x%04x", elementaryPID);
192
193         MY_LOGV("    reserved = %u", br->getBits(4));
194
195         unsigned ES_info_length = br->getBits(12);
196         LOGV("    ES_info_length = %u", ES_info_length);
197         CHECK((ES_info_length & 0xc00) == 0);
198
199         CHECK_GE(infoBytesRemaining - 5, ES_info_length);
200
201 #if 0
202         br->skipBits(ES_info_length * 8);  // skip descriptors
203 #else
204         unsigned info_bytes_remaining = ES_info_length;
205         while (info_bytes_remaining >= 2) {
206             MY_LOGV("      tag = 0x%02x", br->getBits(8));
207
208             unsigned descLength = br->getBits(8);
209             LOGV("      len = %u", descLength);
210
211             CHECK_GE(info_bytes_remaining, 2 + descLength);
212
213             br->skipBits(descLength * 8);
214
215             info_bytes_remaining -= descLength + 2;
216         }
217         CHECK_EQ(info_bytes_remaining, 0u);
218 #endif
219
220         ssize_t index = mStreams.indexOfKey(elementaryPID);
221 #if 0  // XXX revisit
222         CHECK_LT(index, 0);
223         mStreams.add(elementaryPID,
224                      new Stream(this, elementaryPID, streamType));
225 #else
226         if (index < 0) {
227             mStreams.add(elementaryPID,
228                          new Stream(this, elementaryPID, streamType));
229         }
230 #endif
231
232         infoBytesRemaining -= 5 + ES_info_length;
233     }
234
235     CHECK_EQ(infoBytesRemaining, 0u);
236
237     MY_LOGV("  CRC = 0x%08x", br->getBits(32));
238 }
239
240 sp<MediaSource> ATSParser::Program::getSource(SourceType type) {
241     for (size_t i = 0; i < mStreams.size(); ++i) {
242         sp<MediaSource> source = mStreams.editValueAt(i)->getSource(type);
243         if (source != NULL) {
244             return source;
245         }
246     }
247
248     return NULL;
249 }
250
251 int64_t ATSParser::Program::convertPTSToTimestamp(uint64_t PTS) {
252     if (!mFirstPTSValid) {
253         mFirstPTSValid = true;
254         mFirstPTS = PTS;
255         PTS = 0;
256     } else if (PTS < mFirstPTS) {
257         PTS = 0;
258     } else {
259         PTS -= mFirstPTS;
260     }
261
262     return (PTS * 100) / 9;
263 }
264
265 ////////////////////////////////////////////////////////////////////////////////
266
267 ATSParser::Stream::Stream(
268         Program *program, unsigned elementaryPID, unsigned streamType)
269     : mProgram(program),
270       mElementaryPID(elementaryPID),
271       mStreamType(streamType),
272       mBuffer(new ABuffer(128 * 1024)),
273       mPayloadStarted(false),
274       mQueue(streamType == 0x1b
275               ? ElementaryStreamQueue::H264 : ElementaryStreamQueue::AAC) {
276     mBuffer->setRange(0, 0);
277 }
278
279 ATSParser::Stream::~Stream() {
280 }
281
282 void ATSParser::Stream::parse(
283         unsigned payload_unit_start_indicator, ABitReader *br) {
284     if (payload_unit_start_indicator) {
285         if (mPayloadStarted) {
286             // Otherwise we run the danger of receiving the trailing bytes
287             // of a PES packet that we never saw the start of and assuming
288             // we have a a complete PES packet.
289
290             flush();
291         }
292
293         mPayloadStarted = true;
294     }
295
296     if (!mPayloadStarted) {
297         return;
298     }
299
300     size_t payloadSizeBits = br->numBitsLeft();
301     CHECK((payloadSizeBits % 8) == 0);
302
303     CHECK_LE(mBuffer->size() + payloadSizeBits / 8, mBuffer->capacity());
304
305     memcpy(mBuffer->data() + mBuffer->size(), br->data(), payloadSizeBits / 8);
306     mBuffer->setRange(0, mBuffer->size() + payloadSizeBits / 8);
307 }
308
309 void ATSParser::Stream::signalDiscontinuity(bool isASeek) {
310     LOGV("Stream discontinuity");
311     mPayloadStarted = false;
312     mBuffer->setRange(0, 0);
313
314     mQueue.clear();
315
316     if (isASeek) {
317         // This is only a "minor" discontinuity, we stay within the same
318         // bitstream.
319
320         mSource->clear();
321         return;
322     }
323
324     if (mStreamType == 0x1b && mSource != NULL) {
325         // Don't signal discontinuities on audio streams.
326         mSource->queueDiscontinuity();
327     }
328 }
329
330 void ATSParser::Stream::parsePES(ABitReader *br) {
331     unsigned packet_startcode_prefix = br->getBits(24);
332
333     LOGV("packet_startcode_prefix = 0x%08x", packet_startcode_prefix);
334
335     CHECK_EQ(packet_startcode_prefix, 0x000001u);
336
337     unsigned stream_id = br->getBits(8);
338     LOGV("stream_id = 0x%02x", stream_id);
339
340     unsigned PES_packet_length = br->getBits(16);
341     LOGV("PES_packet_length = %u", PES_packet_length);
342
343     if (stream_id != 0xbc  // program_stream_map
344             && stream_id != 0xbe  // padding_stream
345             && stream_id != 0xbf  // private_stream_2
346             && stream_id != 0xf0  // ECM
347             && stream_id != 0xf1  // EMM
348             && stream_id != 0xff  // program_stream_directory
349             && stream_id != 0xf2  // DSMCC
350             && stream_id != 0xf8) {  // H.222.1 type E
351         CHECK_EQ(br->getBits(2), 2u);
352
353         MY_LOGV("PES_scrambling_control = %u", br->getBits(2));
354         MY_LOGV("PES_priority = %u", br->getBits(1));
355         MY_LOGV("data_alignment_indicator = %u", br->getBits(1));
356         MY_LOGV("copyright = %u", br->getBits(1));
357         MY_LOGV("original_or_copy = %u", br->getBits(1));
358
359         unsigned PTS_DTS_flags = br->getBits(2);
360         LOGV("PTS_DTS_flags = %u", PTS_DTS_flags);
361
362         unsigned ESCR_flag = br->getBits(1);
363         LOGV("ESCR_flag = %u", ESCR_flag);
364
365         unsigned ES_rate_flag = br->getBits(1);
366         LOGV("ES_rate_flag = %u", ES_rate_flag);
367
368         unsigned DSM_trick_mode_flag = br->getBits(1);
369         LOGV("DSM_trick_mode_flag = %u", DSM_trick_mode_flag);
370
371         unsigned additional_copy_info_flag = br->getBits(1);
372         LOGV("additional_copy_info_flag = %u", additional_copy_info_flag);
373
374         MY_LOGV("PES_CRC_flag = %u", br->getBits(1));
375         MY_LOGV("PES_extension_flag = %u", br->getBits(1));
376
377         unsigned PES_header_data_length = br->getBits(8);
378         LOGV("PES_header_data_length = %u", PES_header_data_length);
379
380         unsigned optional_bytes_remaining = PES_header_data_length;
381
382         uint64_t PTS = 0, DTS = 0;
383
384         if (PTS_DTS_flags == 2 || PTS_DTS_flags == 3) {
385             CHECK_GE(optional_bytes_remaining, 5u);
386
387             CHECK_EQ(br->getBits(4), PTS_DTS_flags);
388
389             PTS = ((uint64_t)br->getBits(3)) << 30;
390             CHECK_EQ(br->getBits(1), 1u);
391             PTS |= ((uint64_t)br->getBits(15)) << 15;
392             CHECK_EQ(br->getBits(1), 1u);
393             PTS |= br->getBits(15);
394             CHECK_EQ(br->getBits(1), 1u);
395
396             LOGV("PTS = %llu", PTS);
397             // LOGI("PTS = %.2f secs", PTS / 90000.0f);
398
399             optional_bytes_remaining -= 5;
400
401             if (PTS_DTS_flags == 3) {
402                 CHECK_GE(optional_bytes_remaining, 5u);
403
404                 CHECK_EQ(br->getBits(4), 1u);
405
406                 DTS = ((uint64_t)br->getBits(3)) << 30;
407                 CHECK_EQ(br->getBits(1), 1u);
408                 DTS |= ((uint64_t)br->getBits(15)) << 15;
409                 CHECK_EQ(br->getBits(1), 1u);
410                 DTS |= br->getBits(15);
411                 CHECK_EQ(br->getBits(1), 1u);
412
413                 LOGV("DTS = %llu", DTS);
414
415                 optional_bytes_remaining -= 5;
416             }
417         }
418
419         if (ESCR_flag) {
420             CHECK_GE(optional_bytes_remaining, 6u);
421
422             br->getBits(2);
423
424             uint64_t ESCR = ((uint64_t)br->getBits(3)) << 30;
425             CHECK_EQ(br->getBits(1), 1u);
426             ESCR |= ((uint64_t)br->getBits(15)) << 15;
427             CHECK_EQ(br->getBits(1), 1u);
428             ESCR |= br->getBits(15);
429             CHECK_EQ(br->getBits(1), 1u);
430
431             LOGV("ESCR = %llu", ESCR);
432             MY_LOGV("ESCR_extension = %u", br->getBits(9));
433
434             CHECK_EQ(br->getBits(1), 1u);
435
436             optional_bytes_remaining -= 6;
437         }
438
439         if (ES_rate_flag) {
440             CHECK_GE(optional_bytes_remaining, 3u);
441
442             CHECK_EQ(br->getBits(1), 1u);
443             MY_LOGV("ES_rate = %u", br->getBits(22));
444             CHECK_EQ(br->getBits(1), 1u);
445
446             optional_bytes_remaining -= 3;
447         }
448
449         br->skipBits(optional_bytes_remaining * 8);
450
451         // ES data follows.
452
453         if (PES_packet_length != 0) {
454             CHECK_GE(PES_packet_length, PES_header_data_length + 3);
455
456             unsigned dataLength =
457                 PES_packet_length - 3 - PES_header_data_length;
458
459             CHECK_GE(br->numBitsLeft(), dataLength * 8);
460
461             onPayloadData(
462                     PTS_DTS_flags, PTS, DTS, br->data(), dataLength);
463
464             br->skipBits(dataLength * 8);
465         } else {
466             onPayloadData(
467                     PTS_DTS_flags, PTS, DTS,
468                     br->data(), br->numBitsLeft() / 8);
469
470             size_t payloadSizeBits = br->numBitsLeft();
471             CHECK((payloadSizeBits % 8) == 0);
472
473             LOGV("There's %d bytes of payload.", payloadSizeBits / 8);
474         }
475     } else if (stream_id == 0xbe) {  // padding_stream
476         CHECK_NE(PES_packet_length, 0u);
477         br->skipBits(PES_packet_length * 8);
478     } else {
479         CHECK_NE(PES_packet_length, 0u);
480         br->skipBits(PES_packet_length * 8);
481     }
482 }
483
484 void ATSParser::Stream::flush() {
485     if (mBuffer->size() == 0) {
486         return;
487     }
488
489     LOGV("flushing stream 0x%04x size = %d", mElementaryPID, mBuffer->size());
490
491     ABitReader br(mBuffer->data(), mBuffer->size());
492     parsePES(&br);
493
494     mBuffer->setRange(0, 0);
495 }
496
497 void ATSParser::Stream::onPayloadData(
498         unsigned PTS_DTS_flags, uint64_t PTS, uint64_t DTS,
499         const uint8_t *data, size_t size) {
500     LOGV("onPayloadData mStreamType=0x%02x", mStreamType);
501
502     CHECK(PTS_DTS_flags == 2 || PTS_DTS_flags == 3);
503     int64_t timeUs = mProgram->convertPTSToTimestamp(PTS);
504
505     status_t err = mQueue.appendData(data, size, timeUs);
506     CHECK_EQ(err, (status_t)OK);
507
508     sp<ABuffer> accessUnit;
509     while ((accessUnit = mQueue.dequeueAccessUnit()) != NULL) {
510         if (mSource == NULL) {
511             sp<MetaData> meta = mQueue.getFormat();
512
513             if (meta != NULL) {
514                 LOGV("created source!");
515                 mSource = new AnotherPacketSource(meta);
516                 mSource->queueAccessUnit(accessUnit);
517             }
518         } else if (mQueue.getFormat() != NULL) {
519             // After a discontinuity we invalidate the queue's format
520             // and won't enqueue any access units to the source until
521             // the queue has reestablished the new format.
522             mSource->queueAccessUnit(accessUnit);
523         }
524     }
525 }
526
527 sp<MediaSource> ATSParser::Stream::getSource(SourceType type) {
528     if ((type == AVC_VIDEO && mStreamType == 0x1b)
529         || (type == MPEG2ADTS_AUDIO && mStreamType == 0x0f)) {
530         return mSource;
531     }
532
533     return NULL;
534 }
535
536 ////////////////////////////////////////////////////////////////////////////////
537
538 ATSParser::ATSParser() {
539 }
540
541 ATSParser::~ATSParser() {
542 }
543
544 void ATSParser::feedTSPacket(const void *data, size_t size) {
545     CHECK_EQ(size, kTSPacketSize);
546
547     ABitReader br((const uint8_t *)data, kTSPacketSize);
548     parseTS(&br);
549 }
550
551 void ATSParser::signalDiscontinuity(bool isASeek) {
552     for (size_t i = 0; i < mPrograms.size(); ++i) {
553         mPrograms.editItemAt(i)->signalDiscontinuity(isASeek);
554     }
555 }
556
557 void ATSParser::parseProgramAssociationTable(ABitReader *br) {
558     unsigned table_id = br->getBits(8);
559     LOGV("  table_id = %u", table_id);
560     CHECK_EQ(table_id, 0x00u);
561
562     unsigned section_syntax_indictor = br->getBits(1);
563     LOGV("  section_syntax_indictor = %u", section_syntax_indictor);
564     CHECK_EQ(section_syntax_indictor, 1u);
565
566     CHECK_EQ(br->getBits(1), 0u);
567     MY_LOGV("  reserved = %u", br->getBits(2));
568
569     unsigned section_length = br->getBits(12);
570     LOGV("  section_length = %u", section_length);
571     CHECK((section_length & 0xc00) == 0);
572
573     MY_LOGV("  transport_stream_id = %u", br->getBits(16));
574     MY_LOGV("  reserved = %u", br->getBits(2));
575     MY_LOGV("  version_number = %u", br->getBits(5));
576     MY_LOGV("  current_next_indicator = %u", br->getBits(1));
577     MY_LOGV("  section_number = %u", br->getBits(8));
578     MY_LOGV("  last_section_number = %u", br->getBits(8));
579
580     size_t numProgramBytes = (section_length - 5 /* header */ - 4 /* crc */);
581     CHECK_EQ((numProgramBytes % 4), 0u);
582
583     for (size_t i = 0; i < numProgramBytes / 4; ++i) {
584         unsigned program_number = br->getBits(16);
585         LOGV("    program_number = %u", program_number);
586
587         MY_LOGV("    reserved = %u", br->getBits(3));
588
589         if (program_number == 0) {
590             MY_LOGV("    network_PID = 0x%04x", br->getBits(13));
591         } else {
592             unsigned programMapPID = br->getBits(13);
593
594             LOGV("    program_map_PID = 0x%04x", programMapPID);
595
596             mPrograms.push(new Program(programMapPID));
597         }
598     }
599
600     MY_LOGV("  CRC = 0x%08x", br->getBits(32));
601 }
602
603 void ATSParser::parsePID(
604         ABitReader *br, unsigned PID,
605         unsigned payload_unit_start_indicator) {
606     if (PID == 0) {
607         if (payload_unit_start_indicator) {
608             unsigned skip = br->getBits(8);
609             br->skipBits(skip * 8);
610         }
611         parseProgramAssociationTable(br);
612         return;
613     }
614
615     bool handled = false;
616     for (size_t i = 0; i < mPrograms.size(); ++i) {
617         if (mPrograms.editItemAt(i)->parsePID(
618                     PID, payload_unit_start_indicator, br)) {
619             handled = true;
620             break;
621         }
622     }
623
624     if (!handled) {
625         LOGV("PID 0x%04x not handled.", PID);
626     }
627 }
628
629 void ATSParser::parseAdaptationField(ABitReader *br) {
630     unsigned adaptation_field_length = br->getBits(8);
631     if (adaptation_field_length > 0) {
632         br->skipBits(adaptation_field_length * 8);  // XXX
633     }
634 }
635
636 void ATSParser::parseTS(ABitReader *br) {
637     LOGV("---");
638
639     unsigned sync_byte = br->getBits(8);
640     CHECK_EQ(sync_byte, 0x47u);
641
642     MY_LOGV("transport_error_indicator = %u", br->getBits(1));
643
644     unsigned payload_unit_start_indicator = br->getBits(1);
645     LOGV("payload_unit_start_indicator = %u", payload_unit_start_indicator);
646
647     MY_LOGV("transport_priority = %u", br->getBits(1));
648
649     unsigned PID = br->getBits(13);
650     LOGV("PID = 0x%04x", PID);
651
652     MY_LOGV("transport_scrambling_control = %u", br->getBits(2));
653
654     unsigned adaptation_field_control = br->getBits(2);
655     LOGV("adaptation_field_control = %u", adaptation_field_control);
656
657     unsigned continuity_counter = br->getBits(4);
658     LOGV("continuity_counter = %u", continuity_counter);
659
660     // LOGI("PID = 0x%04x, continuity_counter = %u", PID, continuity_counter);
661
662     if (adaptation_field_control == 2 || adaptation_field_control == 3) {
663         parseAdaptationField(br);
664     }
665
666     if (adaptation_field_control == 1 || adaptation_field_control == 3) {
667         parsePID(br, PID, payload_unit_start_indicator);
668     }
669 }
670
671 sp<MediaSource> ATSParser::getSource(SourceType type) {
672     for (size_t i = 0; i < mPrograms.size(); ++i) {
673         sp<MediaSource> source = mPrograms.editItemAt(i)->getSource(type);
674
675         if (source != NULL) {
676             return source;
677         }
678     }
679
680     return NULL;
681 }
682
683 }  // namespace android