สำหรับ Android 11 ขึ้นไป คุณสามารถใช้เฟรมเวิร์ก Android Tuner เพื่อส่งเนื้อหา A/V ได้ เฟรมเวิร์กนี้ใช้ไปป์ไลน์ฮาร์ดแวร์จากผู้ให้บริการ จึงเหมาะสำหรับทั้ง SoC ระดับล่างและระดับสูง เฟรมเวิร์กนี้มีวิธีที่ปลอดภัยในการส่งเนื้อหา A/V ที่ได้รับการปกป้องโดยสภาพแวดล้อมการดำเนินการที่เชื่อถือได้ (TEE) และ Secure Media Path (SMP) ซึ่งช่วยให้สามารถใช้ในสภาพแวดล้อมที่มีการจำกัดอย่างเข้มงวดและมีการปกป้องเนื้อหา
อินเทอร์เฟซที่ได้มาตรฐานระหว่างจูนเนอร์และ CAS ของ Android ทำให้การผสานรวมระหว่างผู้ให้บริการจูนเนอร์และผู้ให้บริการ CAS เร็วขึ้น
อินเทอร์เฟซของจูนเนอร์ทำงานร่วมกับ MediaCodec และ AudioTrack เพื่อสร้างโซลูชันเดียวสำหรับ Android TV
อินเทอร์เฟซจูนเนอร์รองรับทั้งทีวีดิจิทัลและทีวีอนาล็อกตามมาตรฐานการออกอากาศหลัก
คอมโพเนนต์
สำหรับ Android 11 มีคอมโพเนนต์ 3 อย่างที่ออกแบบมาสำหรับแพลตฟอร์มทีวีโดยเฉพาะ
- Tuner HAL: อินเทอร์เฟซระหว่างเฟรมเวิร์กและผู้ให้บริการ
- API ของ Tuner SDK: อินเทอร์เฟซระหว่างเฟรมเวิร์กกับแอป
- ตัวจัดการทรัพยากรจูนเนอร์ (TRM): ประสานงานทรัพยากรฮาร์ดแวร์จูนเนอร์
สำหรับ Android 11 เราได้ปรับปรุงคอมโพเนนต์ต่อไปนี้
- CAS V2
TvInputServiceหรือบริการอินพุตทีวี (TIS)TvInputManagerServiceหรือบริการตัวจัดการอินพุตทีวี (TIMS)MediaCodecหรือตัวแปลงรหัสสื่อAudioTrackหรือแทร็กเสียงMediaResourceManagerหรือ Media Resource Manager (MRM)
รูปที่ 1 การโต้ตอบระหว่างคอมโพเนนต์ของ Android TV
ฟีเจอร์
ส่วนหน้าของแอปพลิเคชันรองรับมาตรฐาน DTV ด้านล่าง
- ATSC
- ATSC3
- DVB C/S/T
- ISDB S/S3/T
- แอนะล็อก
ส่วนหน้าใน Android 12 ที่มี Tuner HAL 1.1 ขึ้นไปรองรับมาตรฐาน DTV ด้านล่าง
- DTMB
Demux รองรับโปรโตคอลสตรีมด้านล่าง
- สตรีมการนำส่ง (TS)
- โปรโตคอลการนำส่งสื่อ MPEG (MMTP)
- Internet Protocol (IP)
- ค่าความยาวประเภท (TLV)
- โปรโตคอลเลเยอร์ลิงก์ ATSC (ALP)
โปรแกรมถอดรหัสรองรับการปกป้องเนื้อหาด้านล่าง
- เส้นทางสื่อที่ปลอดภัย
- ล้างเส้นทางสื่อ
- บันทึกในเครื่องอย่างปลอดภัย
- การเล่นไฟล์ในเครื่องอย่างปลอดภัย
Tuner API รองรับกรณีการใช้งานต่อไปนี้
- สแกน
- สด
- การเล่น
- บันทึก
Tuner, MediaCodec และ AudioTrack รองรับโฟลว์ข้อมูลด้านล่าง
- เพย์โหลด ES ที่มีบัฟเฟอร์หน่วยความจำที่ชัดเจน
- เพย์โหลด ES ที่มีแฮนเดิลหน่วยความจำที่ปลอดภัย
- โปร่ง
การออกแบบโดยรวม
HAL ของ Tuner จะกำหนดระหว่างเฟรมเวิร์ก Android กับฮาร์ดแวร์ของผู้ให้บริการ
- อธิบายสิ่งที่เฟรมเวิร์กคาดหวังจากผู้ให้บริการและวิธีที่ผู้ให้บริการอาจ ดำเนินการ
- ส่งออกฟังก์ชันการทำงานของส่วนหน้า, การแยกมัลติเพล็กซ์ และการถอดรหัสไปยัง
เฟรมเวิร์กผ่านอินเทอร์เฟซ
IFrontend,IDemux,IDescrambler,IFilter,IDvrและILnb - รวมถึงฟังก์ชันต่างๆ ในการผสานรวม Tuner HAL กับคอมโพเนนต์อื่นๆ ของเฟรมเวิร์ก เช่น
MediaCodecและAudioTrack
ระบบจะสร้างคลาส Java ของ Tuner และคลาสเนทีฟ
- Tuner Java API อนุญาตให้แอปเข้าถึง Tuner HAL ผ่าน API สาธารณะ
- คลาสเนทีฟช่วยให้ควบคุมสิทธิ์และจัดการข้อมูลการบันทึกหรือการเล่นจำนวนมากได้ด้วย Tuner HAL
- โมดูล Native Tuner เป็นตัวเชื่อมระหว่างคลาส Tuner Java กับ Tuner HAL
สร้างชั้นเรียน TRM
- จัดการทรัพยากรจูนเนอร์ที่จำกัด เช่น Frontend, LNB, เซสชัน CAS และอุปกรณ์อินพุตทีวีจาก HAL อินพุตทีวี
- ใช้กฎเพื่อเรียกคืนทรัพยากรที่ไม่เพียงพอจาก แอป กฎเริ่มต้นคือการชนะในเบื้องหน้า
เราได้ปรับปรุง Media CAS และ CAS HAL ด้วยฟีเจอร์ต่อไปนี้
- เปิดเซสชัน CAS สำหรับการใช้งานและอัลกอริทึมต่างๆ
- รองรับระบบ CAS แบบไดนามิก เช่น การนำ CICAM ออกและการแทรก
- ผสานรวมกับ Tuner HAL โดยการระบุโทเค็นคีย์
MediaCodec และ AudioTrack ได้รับการปรับปรุงด้วยฟีเจอร์ด้านล่าง
- รับหน่วยความจำ A/V ที่ปลอดภัยเป็นอินพุตเนื้อหา
- กำหนดค่าให้ซิงค์ A/V ของฮาร์ดแวร์ในการเล่นแบบ Tunnel
- รองรับการกำหนดค่าสำหรับ
ES_payloadและโหมดส่งผ่าน
รูปที่ 2 แผนภาพของคอมโพเนนต์ภายใน Tuner HAL
เวิร์กโฟลว์โดยรวม
แผนภาพด้านล่างแสดงลำดับการเรียกสำหรับการเล่นการถ่ายทอดสด
ตั้งค่า
รูปที่ 3 ลำดับการตั้งค่าสำหรับการเล่นการถ่ายทอดสด
การจัดการ A/V
รูปที่ 4 การจัดการ A/V สำหรับการเล่นการถ่ายทอดสด
การจัดการเนื้อหาที่ถูกรบกวน
รูปที่ 5 การจัดการเนื้อหาที่เข้ารหัสสำหรับการเล่นการถ่ายทอดสด
การประมวลผลข้อมูลภาพและเสียง
รูปที่ 6 กำลังประมวลผล A/V สำหรับการเล่นการถ่ายทอดสด
Tuner SDK API
API ของ Tuner SDK จะจัดการการโต้ตอบกับ Tuner JNI, Tuner HAL
และ TunerResourceManager แอป TIS ใช้ Tuner SDK API เพื่อเข้าถึงแหล่งข้อมูลและคอมโพเนนต์ย่อยของ Tuner เช่น ตัวกรองและตัวถอดรหัส Frontend และ
demux เป็นคอมโพเนนต์ภายใน
รูปที่ 7 การโต้ตอบกับ Tuner SDK API
เวอร์ชัน
ตั้งแต่ Android 12 เป็นต้นไป API ของ Tuner SDK จะรองรับฟีเจอร์ใหม่ใน Tuner HAL 1.1 ซึ่ง เป็นการอัปเกรดเวอร์ชัน Tuner 1.0 ที่เข้ากันได้แบบย้อนหลัง
ใช้ API ต่อไปนี้เพื่อตรวจสอบ HAL เวอร์ชันที่ใช้งานอยู่
android.media.tv.tuner.TunerVersionChecker.getTunerVersion()
ดูเวอร์ชัน HAL ขั้นต่ำที่จำเป็นได้ในเอกสารประกอบของ Android 12 API ใหม่
แพ็กเกจ
API ของ Tuner SDK มีแพ็กเกจ 4 รายการด้านล่าง
android.media.tv.tunerandroid.media.tv.tuner.frontendandroid.media.tv.tuner.filterandroid.media.tv.tuner.dvr
รูปที่ 8 แพ็กเกจ API ของ Tuner SDK
Android.media.tv.tuner
แพ็กเกจ Tuner เป็นจุดแรกเข้าในการใช้เฟรมเวิร์ก Tuner แอป TIS ใช้แพ็กเกจเพื่อเริ่มต้นและรับอินสแตนซ์ทรัพยากรโดยการระบุ การตั้งค่าเริ่มต้นและการเรียกกลับ
tuner(): เริ่มต้นอินสแตนซ์ Tuner โดยการระบุพารามิเตอร์useCaseและsessionIdtune(): รับทรัพยากรส่วนหน้าและปรับแต่งโดยการระบุพารามิเตอร์FrontendSettingopenFilter(): รับอินสแตนซ์ตัวกรองโดยการระบุประเภทตัวกรองopenDvrRecorder(): รับอินสแตนซ์การบันทึกโดยการระบุขนาดบัฟเฟอร์openDvrPlayback(): รับอินสแตนซ์การเล่นโดยการระบุขนาดบัฟเฟอร์openDescrambler(): รับอินสแตนซ์การยกเลิกการสุ่มopenLnb(): รับอินสแตนซ์ LNB ภายในopenLnbByName(): รับอินสแตนซ์ LNB ภายนอกopenTimeFilter(): รับอินสแตนซ์ตัวกรองเวลา
แพ็กเกจ Tuner มีฟังก์ชันการทำงานที่ไม่ได้ครอบคลุมอยู่ในแพ็กเกจตัวกรอง DVR และส่วนหน้า ฟังก์ชันการทำงานจะแสดงอยู่ด้านล่าง
cancelTuningscan/cancelScanninggetAvSyncHwIdgetAvSyncTimeconnectCiCam1/disconnectCiCamshareFrontendFromTunerupdateResourcePrioritysetOnTuneEventListenersetResourceLostListener
Android.media.tv.tuner.frontend
แพ็กเกจส่วนหน้าประกอบด้วยชุดการตั้งค่า ข้อมูล สถานะ เหตุการณ์ และความสามารถที่เกี่ยวข้องกับส่วนหน้า
ชั้นเรียน
FrontendSettings ได้รับการอนุพันธ์สำหรับมาตรฐาน DTV ที่แตกต่างกันตามคลาสต่อไปนี้
AnalogFrontendSettingsAtsc3FrontendSettingsAtscFrontendSettingsDvbcFrontendSettingsDvbsFrontendSettingsDvbtFrontendSettingsIsdbs3FrontendSettingsIsdbsFrontendSettingsIsdbtFrontendSettings
ตั้งแต่ Android 12 ที่มี Tuner HAL 1.1 ขึ้นไป ระบบจะรองรับมาตรฐาน DTV ต่อไปนี้
DtmbFrontendSettings
FrontendCapabilities ได้รับการอนุพันธ์สำหรับมาตรฐาน DTV ที่แตกต่างกันตามคลาส
ด้านล่าง
AnalogFrontendCapabilitiesAtsc3FrontendCapabilitiesAtscFrontendCapabilitiesDvbcFrontendCapabilitiesDvbsFrontendCapabilitiesDvbtFrontendCapabilitiesIsdbs3FrontendCapabilitiesIsdbsFrontendCapabilitiesIsdbtFrontendCapabilities
ตั้งแต่ Android 12 ที่มี Tuner HAL 1.1 ขึ้นไป ระบบจะรองรับมาตรฐาน DTV ต่อไปนี้
DtmbFrontendCapabilities
FrontendInfo เรียกข้อมูลของส่วนหน้า
FrontendStatus ดึงสถานะปัจจุบันของส่วนหน้า
OnTuneEventListener จะรับฟังเหตุการณ์ในส่วนหน้า
แอป TIS ใช้ ScanCallback เพื่อประมวลผลข้อความที่สแกนจากส่วนหน้า
สแกนช่อง
หากต้องการตั้งค่าทีวี แอปจะสแกนความถี่ที่เป็นไปได้และสร้างรายการช่อง
เพื่อให้ผู้ใช้เข้าถึงได้ TIS อาจใช้ Tuner.tune,
Tuner.scan(BLIND_SCAN) หรือ Tuner.scan(AUTO_SCAN) เพื่อสแกนช่องให้เสร็จสมบูรณ์
หาก TIS มีข้อมูลการนำส่งที่ถูกต้องสำหรับสัญญาณ เช่น ความถี่
มาตรฐาน (เช่น T/T2, S/S2) และข้อมูลเพิ่มเติมที่จำเป็น
(เช่น รหัส PLD) เราขอแนะนำให้ใช้ Tuner.tune เนื่องจากเป็นตัวเลือกที่เร็วกว่า
เมื่อผู้ใช้โทรหา Tuner.tune จะเกิดการดำเนินการต่อไปนี้
- TIS จะป้อนข้อมูลที่จำเป็นลงใน
FrontendSettingsโดยใช้Tuner.tune - HAL จะรายงานข้อความปรับ
LOCKEDหากล็อกสัญญาณ - TIS ใช้
Frontend.getStatusเพื่อรวบรวมข้อมูลที่จำเป็น - TIS จะเปลี่ยนไปใช้ความถี่ถัดไปที่พร้อมใช้งานในรายการความถี่
TIS จะโทรหา Tuner.tune อีกครั้งจนกว่าจะใช้ความถี่ทั้งหมด
ในระหว่างการปรับ คุณสามารถโทรหา stopTune() หรือ close() เพื่อหยุดชั่วคราวหรือสิ้นสุดการโทร Tuner.tune
Tuner.scan(AUTO_SCAN)
หาก TIS มีข้อมูลไม่เพียงพอที่จะใช้ Tuner.tune แต่มีรายการความถี่และประเภทมาตรฐาน (เช่น DVB T/C/S)
เราขอแนะนำให้ใช้ Tuner.scan(AUTO_SCAN)
เมื่อผู้ใช้โทรหา Tuner.scan(AUTO_SCAN) จะเกิดการดำเนินการต่อไปนี้
TIS ใช้
Tuner.scan(AUTO_SCAN)โดยมีFrontendSettingsที่ระบุความถี่HAL จะรายงานข้อความสแกน
LOCKEDหากล็อกสัญญาณ นอกจากนี้ HAL อาจรายงานข้อความการสแกนอื่นๆ เพื่อให้ข้อมูลเพิ่มเติมเกี่ยวกับสัญญาณด้วยTIS ใช้
Frontend.getStatusเพื่อรวบรวมข้อมูลที่จำเป็นTIS จะเรียก
Tuner.scanเพื่อให้ HAL ดำเนินการตั้งค่าถัดไปในความถี่เดียวกัน หากโครงสร้างFrontendSettingsว่างเปล่า HAL จะใช้การตั้งค่าถัดไป ที่พร้อมใช้งาน ไม่เช่นนั้น HAL จะใช้FrontendSettingsสำหรับการสแกนแบบครั้งเดียว และส่งENDเพื่อระบุว่าการดำเนินการสแกนเสร็จสิ้นแล้วTIS จะทำซ้ำการดำเนินการข้างต้นจนกว่าการตั้งค่าทั้งหมดในความถี่จะ หมด
HAL จะส่ง
ENDเพื่อระบุว่าการสแกนเสร็จสิ้นแล้วTIS จะเปลี่ยนไปใช้ความถี่ถัดไปที่พร้อมใช้งานในรายการความถี่
TIS จะโทรหา Tuner.scan(AUTO_SCAN) อีกครั้งจนกว่าจะใช้ความถี่ทั้งหมด
ในระหว่างการสแกน คุณสามารถโทรหา stopScan() หรือ close() เพื่อหยุดชั่วคราวหรือสิ้นสุดการสแกนได้
Tuner.scan(BLIND_SCAN)
หาก TIS ไม่มีรายการความถี่และ HAL ของผู้ให้บริการค้นหาความถี่ของส่วนหน้า
ที่ผู้ใช้ระบุเพื่อรับทรัพยากรส่วนหน้าได้ เราขอแนะนำให้ใช้ Tuner.scan(BLIND_SCAN)
- TIS ใช้
Tuner.scan(BLIND_SCAN)คุณระบุความถี่ได้ในFrontendSettingsสำหรับความถี่เริ่มต้น แต่ TIS จะไม่สนใจการตั้งค่าอื่นๆ ในFrontendSettings - HAL จะรายงานข้อความ
LOCKEDการสแกนหากล็อกสัญญาณ - TIS ใช้
Frontend.getStatusเพื่อรวบรวมข้อมูลที่จำเป็น - TIS จะโทรหา
Tuner.scanอีกครั้งเพื่อสแกนต่อ (FrontendSettingsจะ ไม่สนใจ) - TIS จะทำซ้ำการดำเนินการข้างต้นจนกว่าการตั้งค่าทั้งหมดในความถี่จะ
หมด HAL จะเพิ่มความถี่โดยที่ TIS ไม่ต้องดำเนินการใดๆ
HAL จะรายงาน
PROGRESS
TIS จะโทรหา Tuner.scan(AUTO_SCAN) อีกครั้งจนกว่าจะใช้ความถี่ทั้งหมด
HAL จะรายงาน END เพื่อระบุว่าการดำเนินการสแกนเสร็จสิ้นแล้ว
ในระหว่างการสแกน คุณสามารถโทรหา stopScan() หรือ close() เพื่อหยุดชั่วคราวหรือสิ้นสุดการสแกน
รูปที่ 9 แผนภาพโฟลว์ของการสแกน TIS
Android.media.tv.tuner.filter
แพ็กเกจตัวกรองคือชุดของการดำเนินการตัวกรองพร้อมกับการกำหนดค่า การตั้งค่า การเรียกกลับ และเหตุการณ์ แพ็กเกจประกอบด้วยการดำเนินการต่อไปนี้ ดูรายการการดำเนินการทั้งหมดได้ในซอร์สโค้ดของ Android
configure()start()stop()flush()read()
ดูรายการทั้งหมดได้ในซอร์สโค้ดของ Android
FilterConfiguration มาจากชั้นเรียนด้านล่าง การกำหนดค่ามีไว้สำหรับประเภทตัวกรองหลัก และระบุโปรโตคอลที่ตัวกรองใช้เพื่อ
ดึงข้อมูล
AlpFilterConfigurationIpFilterConfigurationMmtpFilterConfigurationTlvFilterConfigurationTsFilterConfiguration
การตั้งค่าได้มาจากคลาสต่อไปนี้ การตั้งค่านี้ใช้สำหรับประเภทย่อยของตัวกรอง และระบุประเภทข้อมูลที่ตัวกรองยกเว้นได้
SectionSettingsAvSettingsPesSettingsRecordSettingsDownloadSettings
FilterEvent ได้มาจากคลาสต่อไปนี้เพื่อรายงานเหตุการณ์สำหรับข้อมูลประเภทต่างๆ
SectionEventMediaEventPesEventTsRecordEventMmtpRecordEventTemiEventDownloadEventIpPayloadEvent
ตั้งแต่ Android 12 ที่มี Tuner HAL 1.1 ขึ้นไป ระบบจะรองรับเหตุการณ์ต่อไปนี้
IpCidChangeEventRestartEventScramblingStatusEvent
รูปแบบเหตุการณ์และรูปแบบข้อมูลจากตัวกรอง
| ประเภทฟิลเตอร์ | ธง | กิจกรรม | การดำเนินการกับข้อมูล | รูปแบบข้อมูล |
|---|---|---|---|---|
TS.SECTIONMMTP.SECTIONIP.SECTIONTLV.SECTIONALP.SECTION |
isRaw: |
ต้องระบุ:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWแนะนำ: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
เรียกใช้Filter.read(buffer, offset, adjustedSize)อย่างน้อย 1 ครั้ง
ตามกิจกรรมและกำหนดการภายในระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์ |
แพ็กเกจเซสชันที่ประกอบขึ้น 1 รายการจะได้รับการส่งโฆษณาใน FMQ โดยแพ็กเกจเซสชันอื่น |
isRaw: |
ต้องระบุ:DemuxFilterEvent::DemuxFilterSectionEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWไม่บังคับ: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์ |
||
TS.PES |
isRaw: |
ต้องระบุ:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWแนะนำ: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
เรียกใช้Filter.read(buffer, offset, adjustedSize)อย่างน้อย 1 ครั้ง
ตามกิจกรรมและกำหนดการภายในระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์ |
แพ็กเกจ PES ที่ประกอบแล้ว 1 แพ็กเกจจะได้รับการเติมใน FMQ โดยแพ็กเกจ PES อื่น |
isRaw: |
ต้องระบุ:DemuxFilterEvent::DemuxFilterPesEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWไม่บังคับ: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์ |
||
MMTP.PES |
isRaw: |
ต้องระบุ:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWแนะนำ: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
ตามกำหนดการของกิจกรรมและกำหนดการภายใน ให้เรียกใช้Filter.read(buffer, offset, adjustedSize) อย่างน้อย 1 ครั้ง
ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์ |
แพ็กเกจ MFU ที่ประกอบแล้ว 1 แพ็กเกจจะได้รับการเติมใน FMQ โดยแพ็กเกจ MFU อื่น |
isRaw: |
ต้องระบุ:DemuxFilterEvent::DemuxFilterPesEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWไม่บังคับ: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์ |
||
TS.TS |
ไม่มี | ต้องระบุ:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWแนะนำ: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
ตามกำหนดการของกิจกรรมและกำหนดการภายใน ให้เรียกใช้Filter.read(buffer, offset, adjustedSize) อย่างน้อย 1 ครั้ง
ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์ |
tsที่กรองออกจะได้รับการกรอกใน FMQ ts |
TS.AudioTS.VideoMMTP.AudioMMTP.Video |
isPassthrough: |
ไม่บังคับ:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOW |
ลูกค้าจะเริ่ม MediaCodec ได้หลังจากได้รับ DemuxFilterStatus::DATA_READYไคลเอ็นต์สามารถเรียกใช้ Filter.flush หลังจากได้รับ DemuxFilterStatus::DATA_OVERFLOW |
ไม่มี |
isPassthrough: |
ต้องระบุ:DemuxFilterEvent::DemuxFilterMediaEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWไม่บังคับ: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
วิธีใช้ MediaCodecfor i=0; i<n; i++วิธีใช้เสียงโดยตรงของ AudioTrackfor i=0; i<n; i++ |
ข้อมูล ES หรือข้อมูล ES บางส่วนในหน่วยความจำ ION | |
TS.PCRIP.NTPALP.PTP |
ไม่มี | ต้องระบุ: ไม่มี
ไม่บังคับ: ไม่มี |
ไม่มี | ไม่มี |
TS.RECORD |
ไม่มี | ต้องระบุ: DemuxFilterEvent::DemuxFilterTsRecordEvent[n]RecordStatus::DATA_READYRecordStatus::DATA_OVERFLOWRecordStatus::LOW_WATERRecordStatus::HIGH_WATERไม่บังคับ: DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWDemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
สำหรับข้อมูลดัชนีfor i=0; i<n; i++สำหรับเนื้อหาที่บันทึกไว้ ตาม RecordStatus::*และกำหนดการภายใน ให้ทำ
อย่างใดอย่างหนึ่งต่อไปนี้
|
สําหรับข้อมูลดัชนี: อยู่ในเพย์โหลดของเหตุการณ์ สำหรับเนื้อหาที่บันทึกไว้: สตรีม TS แบบมัลติเพล็กซ์ที่ป้อนใน FMQ |
TS.TEMI |
ไม่มี | ต้องระบุ:DemuxFilterEvent::DemuxFilterTemiEvent[n]ไม่บังคับ: DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWDemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ |
ไม่มี |
MMTP.MMTP |
ไม่มี | ต้องระบุ:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWแนะนำ: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
ตามกำหนดการของกิจกรรมและกำหนดการภายใน ให้เรียกใช้Filter.read(buffer, offset, adjustedSize) อย่างน้อย 1 ครั้ง
ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์ |
mmtpที่กรองออกจะได้รับการกรอกใน FMQ mmtp |
MMTP.RECORD |
ไม่มี | ต้องระบุ:DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n]RecordStatus::DATA_READYRecordStatus::DATA_OVERFLOWRecordStatus::LOW_WATERRecordStatus::HIGH_WATERไม่บังคับ: DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWDemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
สำหรับข้อมูลดัชนี: for i=0; i<n; i++สำหรับเนื้อหาที่บันทึกไว้ ตาม RecordStatus::* และกำหนดการภายใน ให้ทำอย่างใดอย่างหนึ่งต่อไปนี้
|
สําหรับข้อมูลดัชนี: อยู่ในเพย์โหลดของเหตุการณ์ สำหรับเนื้อหาที่บันทึกไว้: สตรีมที่บันทึกไว้แบบมัลติเพล็กซ์ที่กรอกใน FMQ หากแหล่งที่มาของตัวกรองสำหรับการบันทึกคือ TLV.TLV ถึง
IP.IP ที่มีการส่งผ่าน สตรีมที่บันทึกจะมี
TLV และส่วนหัว IP |
MMTP.DOWNLOAD |
ไม่มี | ต้องระบุ:DemuxFilterEvent::DemuxFilterDownloadEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWไม่บังคับ: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterDownloadEvent[i].size)ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์ |
FMQ จะเติมแพ็กเกจดาวน์โหลดด้วยแพ็กเกจดาวน์โหลด IP อื่น |
IP.IP_PAYLOAD |
ไม่มี | ต้องระบุ:DemuxFilterEvent::DemuxFilterIpPayloadEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWไม่บังคับ: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterIpPayloadEvent[i].size)ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์ |
แพ็กเกจเพย์โหลด IP จะได้รับการเติมใน FMQ โดยแพ็กเกจเพย์โหลด IP อื่น |
IP.IPTLV.TLVALP.ALP |
isPassthrough: |
ไม่บังคับ:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOW |
สตรีมย่อยของโปรโตคอลที่กรองออกจะป้อนตัวกรองถัดไปในเชน filter | ไม่มี |
isPassthrough: |
ต้องระบุ:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWแนะนำ: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
ตามกำหนดการของกิจกรรมและกำหนดการภายใน ให้เรียกใช้Filter.read(buffer, offset, adjustedSize) อย่างน้อย 1 ครั้ง
ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์ |
กรองสตรีมย่อยของโปรโตคอลออกและกรอกส่วนหัวของโปรโตคอล FMQ | |
IP.PAYLOAD_THROUGHTLV.PAYLOAD_THROUGHALP.PAYLOAD_THROUGH |
ไม่มี | ไม่บังคับ:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOW |
ฟีดเพย์โหลดของโปรโตคอลที่กรองออกจะป้อนตัวกรองถัดไปในเชน filter | ไม่มี |
ตัวอย่างโฟลว์ในการใช้ตัวกรองเพื่อสร้าง PSI/SI
รูปที่ 10 ขั้นตอนการสร้าง PSI/SI
เปิดตัวกรอง
Filter filter = tuner.openFilter( Filter.TYPE_TS, Filter.SUBTYPE_SECTION, /* bufferSize */1000, executor, filterCallback );กำหนดค่าและเริ่มตัวกรอง
Settings settings = SectionSettingsWithTableInfo .builder(Filter.TYPE_TS) .setTableId(2) .setVersion(1) .setCrcEnabled(true) .setRaw(false) .setRepeat(false) .build(); FilterConfiguration config = TsFilterConfiguration .builder() .setTpid(10) .setSettings(settings) .build(); filter.configure(config); filter.start();ดำเนินการ
SectionEventFilterCallback filterCallback = new FilterCallback() { @Override public void onFilterEvent(Filter filter, FilterEvent[] events) { for (FilterEvent event : events) { if (event instanceof SectionEvent) { SectionEvent sectionEvent = (SectionEvent) event; int tableId = sectionEvent.getTableId(); int version = sectionEvent.getVersion(); int dataLength = sectionEvent.getDataLength(); int sectionNumber = sectionEvent.getSectionNumber(); filter.read(buffer, 0, dataLength); } } } };
ตัวอย่างโฟลว์ในการใช้ MediaEvent จากตัวกรอง
รูปที่ 11 Flow ในการใช้ MediaEvent จากตัวกรอง
- เปิด กำหนดค่า และเริ่มตัวกรอง A/V
- ดำเนินการ
MediaEvent - รับ
MediaEvent - จัดคิวโฆษณาเชิงเส้นไปยัง
codec - ปล่อยแฮนเดิล A/V เมื่อใช้ข้อมูลแล้ว
Android.media.tv.tuner.dvr
DvrRecorder มีวิธีการบันทึกต่อไปนี้
configureattachFilterdetachFilterstartflushstopsetFileDescriptorwrite
DvrPlayback มีวิธีการเหล่านี้สำหรับการเล่น
configurestartflushstopsetFileDescriptorread
ใช้ DvrSettings เพื่อกำหนดค่า DvrRecorder และ DvrPlayback
OnPlaybackStatusChangedListener และ OnRecordStatusChangedListener ใช้เพื่อรายงานสถานะของอินสแตนซ์ DVR
ตัวอย่างโฟลว์เพื่อเริ่มบันทึก
รูปที่ 12 ขั้นตอนการเริ่มบันทึก
เปิด กำหนดค่า และเริ่ม
DvrRecorderDvrRecorder recorder = openDvrRecorder(/* bufferSize */ 1000, executor, listener); DvrSettings dvrSettings = DvrSettings .builder() .setDataFormat(DvrSettings.DATA_FORMAT_TS) .setLowThreshold(100) .setHighThreshold(900) .setPacketSize(188) .build(); recorder.configure(dvrSettings); recorder.attachFilter(filter); recorder.setFileDescriptor(fd); recorder.start();รับ
RecordEventและดึงข้อมูลดัชนีFilterCallback filterCallback = new FilterCallback() { @Override public void onFilterEvent(Filter filter, FilterEvent[] events) { for (FilterEvent event : events) { if (event instanceof TsRecordEvent) { TsRecordEvent recordEvent = (TsRecordEvent) event; int tsMask = recordEvent.getTsIndexMask(); int scMask = recordEvent.getScIndexMask(); int packetId = recordEvent.getPacketId(); long dataLength = recordEvent.getDataLength(); // handle the masks etc. } } } };เริ่มต้น
OnRecordStatusChangedListenerและจัดเก็บข้อมูลบันทึกOnRecordStatusChangedListener listener = new OnRecordStatusChangedListener() { @Override public void onRecordStatusChanged(int status) { // a customized way to consume data efficiently by using status as a hint. if (status == Filter.STATUS_DATA_READY) { recorder.write(size); } } };
HAL ตัวรับสัญญาณ
Tuner HAL เป็นไปตาม HIDL และกำหนดอินเทอร์เฟซระหว่างเฟรมเวิร์กกับฮาร์ดแวร์ของผู้ให้บริการ ผู้ให้บริการใช้อินเทอร์เฟซเพื่อติดตั้งใช้งาน Tuner HAL และ เฟรมเวิร์กจะใช้อินเทอร์เฟซนี้เพื่อสื่อสารกับการติดตั้งใช้งาน Tuner HAL
โมดูล
Tuner HAL 1.0
| โมดูล | การควบคุมพื้นฐาน | การควบคุมเฉพาะโมดูล | ไฟล์ HAL |
|---|---|---|---|
ITuner |
ไม่มี | frontend(open, getIds, getInfo), openDemux,
openDescrambler, openLnb,
getDemuxCaps |
ITuner.hal |
IFrontend |
setCallback, getStatus, close
| tune, stopTune, scan,
stopScan, setLnb |
IFrontend.halIFrontendCallback.hal |
IDemux |
close |
setFrontendDataSource, openFilter, openDvr, getAvSyncHwId,
getAvSyncTime, connect / disconnectCiCam |
IDemux.hal |
IDvr |
close, start, stop, configure |
attach/detachFilters, flush, getQueueDesc |
IDvr.halIDvrCallback.hal |
IFilter |
close, start, stop, configure, getId |
flush, getQueueDesc, releaseAvHandle, setDataSource |
IFilter.halIFilterCallback.hal |
ILnb |
close, setCallback |
setVoltage, setTone, setSatellitePosition, sendDiseqcMessage |
ILnb.halILnbCallback.hal |
IDescrambler |
close |
setDemuxSource, setKeyToken,
addPid, removePid |
IDescrambler.hal |
Tuner HAL 1.1 (ได้มาจาก Tuner HAL 1.0)
| โมดูล | การควบคุมพื้นฐาน | การควบคุมเฉพาะโมดูล | ไฟล์ HAL |
|---|---|---|---|
ITuner |
ไม่มี | getFrontendDtmbCapabilities |
@1.1::ITuner.hal |
IFrontend |
tune_1_1, scan_1_1, getStatusExt1_1 |
link/unlinkCiCam |
@1.1::IFrontend.hal@1.1::IFrontendCallback.hal |
IFilter |
getStatusExt1_1 |
configureIpCid, configureAvStreamType, getAvSharedHandle, configureMonitorEvent |
@1.1::IFilter.hal@1.1::IFilterCallback.hal |
รูปที่ 13 แผนภาพการโต้ตอบระหว่างโมดูล HAL ของจูนเนอร์
การเชื่อมโยงตัวกรอง
Tuner HAL รองรับการเชื่อมโยงตัวกรองเพื่อให้ตัวกรองลิงก์กับตัวกรองอื่นๆ สำหรับหลายเลเยอร์ได้ ตัวกรองจะทำตามกฎต่อไปนี้
- ตัวกรองจะลิงก์เป็นโครงสร้างแบบต้นไม้ และไม่อนุญาตให้ใช้เส้นทางที่ปิด
- โหนดรูทคือ demux
- ฟิลเตอร์จะทำงานแยกกัน
- ตัวกรองทั้งหมดเริ่มรับข้อมูล
- การเชื่อมโยงตัวกรองจะล้างในตัวกรองสุดท้าย
โค้ดบล็อกด้านล่างและรูปที่ 14 แสดงตัวอย่างการกรองเลเยอร์หลายรายการ
demuxCaps = ITuner.getDemuxCap;
If (demuxCaps[IP][MMTP] == true) {
ipFilter = ITuner.openFilter(<IP, ..>)
mmtpFilter1 = ITuner.openFilter(<MMTP ..>)
mmtpFilter2 = ITuner.openFilter(<MMTP ..>)
mmtpFilter1.setDataSource(<ipFilter>)
mmtpFilter2.setDataSource(<ipFilter>)
}
รูปที่ 14 แผนภาพโฟลว์ของการเชื่อมโยงตัวกรองสำหรับหลายเลเยอร์
เครื่องมือจัดการทรัพยากรของตัวรับสัญญาณ
ก่อนมี Tuner Resource Manager (TRM) การสลับระหว่าง 2 แอปต้องใช้ฮาร์ดแวร์จูนเนอร์เดียวกัน TV Input Framework (TIF) ใช้กลไก "ใครได้ก่อนชนะ" ซึ่งหมายความว่าแอปใดก็ตามที่ได้รับทรัพยากรก่อนจะเก็บทรัพยากรนั้นไว้ อย่างไรก็ตาม กลไกนี้อาจไม่เหมาะกับ Use Case ที่ซับซ้อนบางอย่าง
TRM ทำงานเป็นบริการของระบบเพื่อจัดการฮาร์ดแวร์จูนเนอร์ TVInput และ CAS
สำหรับแอป TRM ใช้กลไก "ชนะในเบื้องหน้า" ซึ่งจะคำนวณลำดับความสำคัญของแอปตามสถานะเบื้องหน้าหรือเบื้องหลังของแอปและประเภท Use Case TRM จะให้หรือเพิกถอนทรัพยากรตาม
ลำดับความสำคัญ TRM รวมศูนย์การจัดการทรัพยากร ATV สำหรับการออกอากาศ, OTT
และ DVR
อินเทอร์เฟซ TRM
TRM จะแสดงอินเทอร์เฟซ AIDL ใน ITunerResourceManager.aidl สำหรับเฟรมเวิร์ก Tuner
MediaCas และ TvInputHardwareManager เพื่อลงทะเบียน ขอ หรือ
ปล่อยทรัพยากร
อินเทอร์เฟซสำหรับการจัดการลูกค้าแสดงอยู่ด้านล่าง
registerClientProfile(in ResourceClientProfile profile, IResourcesReclaimListener listener, out int[] clientId)unregisterClientProfile(in int clientId)
อินเทอร์เฟซสำหรับขอและปล่อยทรัพยากรแสดงอยู่ด้านล่าง
requestFrontend(TunerFrontendRequest request, int[] frontendHandle)/releaseFrontendrequestDemux(TunerDemuxRequest request, int[] demuxHandle)/releaseDemuxrequestDescrambler(TunerDescramblerRequest request, int[] descramblerHandle)/releaseDescramblerrequestCasSession(CasSessionRequest request, int[] casSessionHandle)/releaseCasSessionrequestLnb(TunerLnbRequest request, int[] lnbHandle)/releaseLnb
คลาสไคลเอ็นต์และคำขอแสดงอยู่ด้านล่าง
ResourceClientProfileResourcesReclaimListenerTunerFrontendRequestTunerDemuxRequestTunerDescramblerRequestCasSessionRequestTunerLnbRequest
ลำดับความสำคัญของไคลเอ็นต์
TRM จะคำนวณลำดับความสำคัญของไคลเอ็นต์โดยใช้พารามิเตอร์จากโปรไฟล์ของไคลเอ็นต์ และค่าลำดับความสำคัญจากไฟล์การกำหนดค่า ไคลเอ็นต์อาจอัปเดตลำดับความสำคัญด้วยค่าลำดับความสำคัญที่กำหนดเองได้ด้วย
พารามิเตอร์ในโปรไฟล์ของลูกค้า
TRM จะดึงข้อมูลรหัสกระบวนการจาก mTvInputSessionId เพื่อพิจารณาว่าแอป
เป็นแอปที่ทำงานอยู่เบื้องหน้าหรือเบื้องหลัง ในการสร้าง mTvInputSessionId
TvInputService.onCreateSession หรือ TvInputService.onCreateRecordingSession
จะเริ่มต้นเซสชัน TIS
mUseCase ระบุกรณีการใช้งานของเซสชัน Use Case ที่กำหนดไว้ล่วงหน้ามีดังนี้
TvInputService.PriorityHintUseCaseType {
PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK
PRIORITY_HINT_USE_CASE_TYPE_LIVE
PRIORITY_HINT_USE_CASE_TYPE_RECORD,
PRIORITY_HINT_USE_CASE_TYPE_SCAN,
PRIORITY_HINT_USE_CASE_TYPE_BACKGROUND
}
ไฟล์การกำหนดค่า
ไฟล์การกำหนดค่าเริ่มต้น
ไฟล์การกำหนดค่าเริ่มต้นด้านล่างระบุค่าลำดับความสำคัญสำหรับกรณีการใช้งานที่กำหนดไว้ล่วงหน้า ผู้ใช้สามารถเปลี่ยนค่าได้โดยใช้ไฟล์การกำหนดค่าที่กำหนดเอง
| กรณีการใช้งาน | ฉากหน้า | ฉากหลัง |
|---|---|---|
LIVE |
490 | 400 |
PLAYBACK |
480 | 300 |
RECORD |
600 | 500 |
SCAN |
450 | 200 |
BACKGROUND |
180 | 100 |
ไฟล์การกำหนดค่าที่ปรับแต่ง
ผู้ให้บริการสามารถปรับแต่งไฟล์การกำหนดค่า
/vendor/etc/tunerResourceManagerUseCaseConfig.xmlได้ ไฟล์นี้ใช้
เพื่อเพิ่ม นำออก หรืออัปเดตประเภท Use Case และค่าลำดับความสำคัญของ Use Case
ไฟล์ที่ปรับแต่งแล้วสามารถใช้
platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml
เป็นเทมเพลตได้
ตัวอย่างเช่น กรณีการใช้งานผู้ให้บริการรายใหม่คือ VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000]
รูปแบบควรเป็นไปตาม
platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd
ค่าลำดับความสำคัญที่กำหนดเองและค่า Nice
TRM มี updateClientPriority ให้ไคลเอ็นต์อัปเดตค่าลำดับความสำคัญที่กำหนดเองและค่า nice
ค่าลำดับความสำคัญที่กำหนดเองจะเขียนทับค่าลำดับความสำคัญที่คำนวณ
จากประเภทกรณีการใช้งานและรหัสเซสชัน
ค่าความดีจะระบุว่าไคลเอ็นต์มีความยืดหยุ่นเพียงใดเมื่อเกิดความขัดแย้งกับไคลเอ็นต์อื่น ค่า nice จะลดค่าลำดับความสำคัญของไคลเอ็นต์ ก่อนที่จะเปรียบเทียบค่าลำดับความสำคัญกับไคลเอ็นต์ที่ท้าทาย
กลไกการเรียกคืน
แผนภาพด้านล่างแสดงวิธีเรียกคืนและกำหนดแหล่งข้อมูลใหม่เมื่อเกิด ความขัดแย้งของแหล่งข้อมูล
รูปที่ 15 แผนภาพของกลไกการเรียกคืนสำหรับความขัดแย้งระหว่างทรัพยากรของจูนเนอร์