สำหรับ Android 11 ขึ้นไป คุณสามารถใช้เฟรมเวิร์ก Android TUNER เพื่อส่งเนื้อหา A/V เฟรมเวิร์กนี้ใช้ไปป์ไลน์ฮาร์ดแวร์จากผู้ให้บริการ จึงเหมาะสำหรับทั้ง SoC ระดับล่างและระดับสูง เฟรมเวิร์กนี้มอบวิธีส่งเนื้อหา A/V ที่ปลอดภัยซึ่งได้รับการปกป้องโดยสภาพแวดล้อมการประมวลผลที่เชื่อถือได้ (TEE) และเส้นทางสื่อที่ปลอดภัย (SMP) จึงนำไปใช้ในสภาพแวดล้อมที่มีการปกป้องเนื้อหาอย่างเข้มงวดได้
อินเทอร์เฟซมาตรฐานระหว่างตัวรับสัญญาณกับ Android CAS ช่วยให้ผสานรวมระหว่างผู้ให้บริการตัวรับสัญญาณกับผู้ให้บริการ CAS ได้เร็วขึ้น อินเทอร์เฟซของโปรแกรมจูนใช้ร่วมกับ MediaCodec
และ AudioTrack
เพื่อสร้างโซลูชันแบบครบวงจรสำหรับ Android TV
อินเทอร์เฟซของจูนเนอร์รองรับทั้งทีวีดิจิทัลและทีวีอนาล็อกตามมาตรฐานการออกอากาศหลักๆ
คอมโพเนนต์
สำหรับ Android 11 คอมโพเนนต์ 3 รายการได้รับการออกแบบมาเพื่อแพลตฟอร์มทีวีโดยเฉพาะ
- Tuner HAL: อินเทอร์เฟซระหว่างเฟรมเวิร์กกับผู้ให้บริการ
- Tuner SDK API: อินเทอร์เฟซระหว่างเฟรมเวิร์กกับแอป
- เครื่องมือจัดการทรัพยากรของจูนเนอร์ (TRM): ประสานทรัพยากรฮาร์ดแวร์ของจูนเนอร์
สำหรับ Android 11 เราได้ปรับปรุงคอมโพเนนต์ต่อไปนี้
- CAS V2
TvInputService
หรือบริการอินพุตทีวี (TIS)TvInputManagerService
หรือบริการ TV Input Manager (TIMS)MediaCodec
หรือตัวแปลงรหัสสื่อAudioTrack
หรือแทร็กเสียงMediaResourceManager
หรือเครื่องมือจัดการทรัพยากรสื่อ (MRM)
รูปที่ 1 การโต้ตอบระหว่างคอมโพเนนต์ Android TV
ฟีเจอร์
ฟรอนต์เอนด์รองรับมาตรฐาน DTV ด้านล่าง
- ATSC
- ATSC3
- DVB C/S/T
- ISDB S/S3/T
- แอนะล็อก
อินเทอร์เฟซส่วนหน้าใน Android 12 ที่มี Tuner HAL 1.1 ขึ้นไปรองรับมาตรฐาน DTV ด้านล่าง
- DTMB
การแยกข้อมูลรองรับโปรโตคอลสตรีมด้านล่าง
- สตรีมการนำส่ง (TS)
- โปรโตคอลการนำส่งสื่อ MPEG (MMTP)
- โปรโตคอลอินเทอร์เน็ต (IP)
- ค่าความยาวประเภท (TLV)
- โปรโตคอลเลเยอร์ลิงก์ ATSC (ALP)
โปรแกรมถอดรหัสรองรับการป้องกันเนื้อหาต่อไปนี้
- เส้นทางสื่อที่ปลอดภัย
- ล้างเส้นทางสื่อ
- บันทึกในเครื่องที่ปลอดภัย
- การเล่นในเครื่องที่ปลอดภัย
Tuner API รองรับกรณีการใช้งานด้านล่าง
- สแกน
- สด
- การเล่น
- บันทึก
Tuner, MediaCodec
และ AudioTrack
รองรับโหมดการไหลของข้อมูลด้านล่าง
- เพย์โหลด ES ที่มีบัฟเฟอร์หน่วยความจําที่ล้างแล้ว
- เพย์โหลด ES ที่มีแฮนเดิลหน่วยความจำที่ปลอดภัย
- การแสดงภาพ
การออกแบบโดยรวม
HAL ของ Tuner จะกำหนดระหว่างเฟรมเวิร์ก Android กับฮาร์ดแวร์ของผู้ให้บริการ
- อธิบายสิ่งที่เฟรมเวิร์กคาดหวังจากผู้ให้บริการและวิธีที่ผู้ให้บริการอาจดำเนินการ
- ส่งออกฟังก์ชันการทำงานของส่วนหน้า โปรแกรมแยกข้อมูล และโปรแกรมถอดรหัสไปยังเฟรมเวิร์กผ่านอินเทอร์เฟซ
IFrontend
,IDemux
,IDescrambler
,IFilter
,IDvr
และILnb
- มีฟังก์ชันในการผสานรวม HAL ของ Tuner กับคอมโพเนนต์เฟรมเวิร์กอื่นๆ เช่น
MediaCodec
และAudioTrack
ระบบจะสร้างคลาส Java และคลาสเนทีฟของ Tuner
- Tuner Java API อนุญาตให้แอปเข้าถึง Tuner HAL ผ่าน API สาธารณะ
- คลาสเนทีฟช่วยให้ควบคุมสิทธิ์และจัดการข้อมูลการบันทึกหรือการเล่นจำนวนมากด้วย Tuner HAL ได้
- โมดูล Tuner เดิมเป็นบริดจ์ระหว่างคลาส Java ของ Tuner กับ Tuner HAL
ระบบจะสร้างคลาส TRM
- จัดการทรัพยากรจูนเนอร์ที่จำกัด เช่น ฟรอนเทนเอนด์, LNB, เซสชัน CAS และอุปกรณ์อินพุตทีวีจาก HAL อินพุตทีวี
- ใช้กฎเพื่อเรียกคืนทรัพยากรที่ไม่เพียงพอจากแอป กฎเริ่มต้นคือโฟกัสอยู่เบื้องหน้าจะชนะ
Media CAS และ CAS HAL ได้รับการปรับปรุงด้วยฟีเจอร์ด้านล่าง
- เปิดเซสชัน CAS สําหรับการใช้งานและอัลกอริทึมที่แตกต่างกัน
- รองรับระบบ CAS แบบไดนามิก เช่น การนำ CICAM ออกและแทรก CICAM
- ผสานรวมกับ Tuner HAL ด้วยการระบุโทเค็นคีย์
MediaCodec
และ AudioTrack
ได้รับการปรับปรุงด้วยฟีเจอร์ด้านล่าง
- ใช้หน่วยความจำ A/V ที่ปลอดภัยเป็นอินพุตเนื้อหา
- กำหนดค่าให้ทำการซิงค์ A/V ของฮาร์ดแวร์ในการเล่นแบบใช้อุโมงค์
- กำหนดค่าการรองรับ
ES_payload
และโหมดการส่งผ่านแล้ว
รูปที่ 2 แผนภาพส่วนประกอบภายใน HAL ของจูนเนอร์
เวิร์กโฟลว์โดยรวม
แผนภาพด้านล่างแสดงลําดับการเรียกใช้สําหรับการเล่นการถ่ายทอดสด
ตั้งค่า
รูปที่ 3 ลำดับการตั้งค่าสำหรับการเล่นสตรีมแบบสด
การจัดการ A/V
รูปที่ 4 การจัดการ A/V สำหรับการถ่ายทอดสด
การจัดการเนื้อหาที่มีการสับเปลี่ยน
รูปที่ 5 การจัดการเนื้อหาที่มีการสับเปลี่ยนสำหรับการเล่นการถ่ายทอดสด
การประมวลผลข้อมูล A/V
รูปที่ 6 กำลังประมวลผล A/V สำหรับการถ่ายทอดสด
Tuner SDK API
Tuner SDK API จะจัดการการโต้ตอบกับ Tuner JNI, Tuner HAL และ TunerResourceManager
แอป TIS ใช้ Tuner SDK API เพื่อเข้าถึงทรัพยากรและคอมโพเนนต์ย่อยของ Tuner เช่น ตัวกรองและโปรแกรมถอดรหัส ส่วนหน้าและตัวแยกสัญญาณเป็นคอมโพเนนต์ภายใน
รูปที่ 7 การโต้ตอบกับ Tuner SDK API
เวอร์ชัน
ตั้งแต่ Android 12 เป็นต้นไป Tuner SDK API จะรองรับฟีเจอร์ใหม่ใน Tuner HAL 1.1 ซึ่งเป็นการอัปเกรดเวอร์ชันที่ใช้งานร่วมกันได้แบบย้อนหลังของ Tuner 1.0
ใช้ API ต่อไปนี้เพื่อตรวจสอบเวอร์ชัน HAL ที่ใช้งานอยู่
android.media.tv.tuner.TunerVersionChecker.getTunerVersion()
ดูเวอร์ชัน HAL ขั้นต่ำที่จำเป็นได้ในเอกสารประกอบของ Android 12 API ใหม่
แพ็กเกจ
Tuner SDK API มีแพ็กเกจ 4 รายการด้านล่างนี้
android.media.tv.tuner
android.media.tv.tuner.frontend
android.media.tv.tuner.filter
android.media.tv.tuner.dvr
รูปที่ 8 แพ็กเกจ Tuner SDK API
Android.media.tv.tuner
แพ็กเกจ Tuner คือจุดแรกเข้าเพื่อใช้เฟรมเวิร์ก Tuner แอป TIS ใช้แพ็กเกจเพื่อเริ่มต้นและรับอินสแตนซ์ทรัพยากรโดยระบุการตั้งค่าเริ่มต้นและการเรียกกลับ
tuner()
: เริ่มต้นอินสแตนซ์ Tuner โดยระบุพารามิเตอร์useCase
และsessionId
tune()
: รับทรัพยากรส่วนหน้าและปรับแต่งโดยระบุพารามิเตอร์FrontendSetting
openFilter()
: รับอินสแตนซ์ตัวกรองโดยระบุประเภทตัวกรองopenDvrRecorder()
: รับอินสแตนซ์การบันทึกโดยระบุขนาดบัฟเฟอร์openDvrPlayback()
: รับอินสแตนซ์การเล่นโดยระบุขนาดบัฟเฟอร์openDescrambler()
: รับอินสแตนซ์โปรแกรมถอดรหัสopenLnb()
: รับอินสแตนซ์ LNB ภายในopenLnbByName()
: รับอินสแตนซ์ LNB ภายนอกopenTimeFilter()
: รับอินสแตนซ์ตัวกรองเวลา
แพ็กเกจ Tuner มีฟังก์ชันการทำงานที่ไม่ครอบคลุมในแพ็กเกจตัวกรอง, DVR และส่วนหน้า ฟังก์ชันการทำงานมีดังนี้
cancelTuning
scan
/cancelScanning
getAvSyncHwId
getAvSyncTime
connectCiCam1
/disconnectCiCam
shareFrontendFromTuner
updateResourcePriority
setOnTuneEventListener
setResourceLostListener
Android.media.tv.tuner.frontend
แพ็กเกจส่วนหน้าประกอบด้วยคอลเล็กชันการตั้งค่า ข้อมูล สถานะ เหตุการณ์ และความสามารถที่เกี่ยวข้องกับส่วนหน้า
ชั้นเรียน
FrontendSettings
มาจากมาตรฐาน DTV ที่แตกต่างกันตามคลาสด้านล่าง
AnalogFrontendSettings
Atsc3FrontendSettings
AtscFrontendSettings
DvbcFrontendSettings
DvbsFrontendSettings
DvbtFrontendSettings
Isdbs3FrontendSettings
IsdbsFrontendSettings
IsdbtFrontendSettings
ตั้งแต่ Android 12 ที่มี Tuner HAL 1.1 ขึ้นไป ระบบจะรองรับมาตรฐาน DTV ต่อไปนี้
DtmbFrontendSettings
FrontendCapabilities
มาจากมาตรฐาน DTV ที่แตกต่างกันตามคลาสด้านล่าง
AnalogFrontendCapabilities
Atsc3FrontendCapabilities
AtscFrontendCapabilities
DvbcFrontendCapabilities
DvbsFrontendCapabilities
DvbtFrontendCapabilities
Isdbs3FrontendCapabilities
IsdbsFrontendCapabilities
IsdbtFrontendCapabilities
ตั้งแต่ 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
มาจากคลาสด้านล่าง การกําหนดค่ามีไว้สําหรับตัวกรองประเภทหลักและระบุโปรโตคอลที่ตัวกรองใช้ดึงข้อมูล
AlpFilterConfiguration
IpFilterConfiguration
MmtpFilterConfiguration
TlvFilterConfiguration
TsFilterConfiguration
การตั้งค่าเหล่านี้มาจากคลาสด้านล่าง การตั้งค่านี้มีไว้สำหรับตัวกรองย่อยและจะระบุประเภทข้อมูลซึ่งตัวกรองจะยกเว้นได้
SectionSettings
AvSettings
PesSettings
RecordSettings
DownloadSettings
FilterEvent
มาจากคลาสด้านล่างเพื่อรายงานเหตุการณ์สําหรับข้อมูลประเภทต่างๆ
SectionEvent
MediaEvent
PesEvent
TsRecordEvent
MmtpRecordEvent
TemiEvent
DownloadEvent
IpPayloadEvent
ตั้งแต่ Android 12 ที่มี Tuner HAL 1.1 ขึ้นไป ระบบจะรองรับเหตุการณ์ต่อไปนี้
IpCidChangeEvent
RestartEvent
ScramblingStatusEvent
เหตุการณ์และรูปแบบข้อมูลจากตัวกรอง
ประเภทตัวกรอง | ธง | กิจกรรม | การดำเนินการกับข้อมูล | รูปแบบข้อมูล |
---|---|---|---|---|
TS.SECTION MMTP.SECTION IP.SECTION TLV.SECTION ALP.SECTION |
isRaw: |
ต้องระบุ:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW แนะนำ: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
เรียกใช้Filter.read(buffer, offset, adjustedSize) อย่างน้อย 1 ครั้งตามเหตุการณ์และกำหนดเวลาภายในระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์ |
แพ็กเกจเซสชันที่ประกอบขึ้น 1 รายการจะได้รับการบรรจุใน FMQ โดยแพ็กเกจเซสชันอื่น |
isRaw: |
ต้องระบุ:DemuxFilterEvent::DemuxFilterSectionEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW ไม่บังคับ: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์ |
||
TS.PES |
isRaw: |
ต้องระบุ:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW แนะนำ: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
เรียกใช้Filter.read(buffer, offset, adjustedSize) อย่างน้อย 1 ครั้งตามเหตุการณ์และกำหนดเวลาภายในระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์ |
แพ็กเกจ PES ที่ประกอบแล้ว 1 รายการจะกรอกข้อมูลใน FMQ โดยแพ็กเกจ PES อื่น |
isRaw: |
ต้องระบุ:DemuxFilterEvent::DemuxFilterPesEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW ไม่บังคับ: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์ |
||
MMTP.PES |
isRaw: |
ต้องระบุ:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW แนะนำ: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
เรียกใช้Filter.read(buffer, offset, adjustedSize) อย่างน้อย 1 ครั้งตามเหตุการณ์และกำหนดการภายในระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์ |
แพ็กเกจ MFU ที่ประกอบแล้ว 1 รายการจะบรรจุใน FMQ โดยแพ็กเกจ MFU อื่น |
isRaw: |
ต้องระบุ:DemuxFilterEvent::DemuxFilterPesEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW ไม่บังคับ: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์ |
||
TS.TS |
ไม่มี | ต้องระบุ:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW แนะนำ: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
เรียกใช้Filter.read(buffer, offset, adjustedSize) อย่างน้อย 1 ครั้งตามเหตุการณ์และกำหนดการภายในระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์ |
ts ที่กรองออกซึ่งมีส่วนหัว ts กรอกใน FMQ |
TS.Audio TS.Video MMTP.Audio MMTP.Video |
isPassthrough: |
ไม่บังคับ:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
ลูกค้าจะเริ่ม MediaCodec ได้หลังจากได้รับ DemuxFilterStatus::DATA_READY ไคลเอ็นต์จะโทรหา Filter.flush ได้หลังจากได้รับ DemuxFilterStatus::DATA_OVERFLOW |
ไม่มี |
isPassthrough: |
ต้องระบุ:DemuxFilterEvent::DemuxFilterMediaEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW ไม่บังคับ: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
วิธีใช้ MediaCodec for i=0; i<n; i++ วิธีใช้เสียงโดยตรงของ AudioTrack for i=0; i<n; i++ |
ES หรือข้อมูล ES บางส่วนในหน่วยความจํา ION | |
TS.PCR IP.NTP ALP.PTP |
ไม่มี | ต้องระบุ: ไม่มี
ไม่บังคับ: ไม่มี |
ไม่มี | ไม่มีข้อมูล |
TS.RECORD |
ไม่มี | ต้องระบุ: DemuxFilterEvent::DemuxFilterTsRecordEvent[n] RecordStatus::DATA_READY RecordStatus::DATA_OVERFLOW RecordStatus::LOW_WATER RecordStatus::HIGH_WATER ไม่บังคับ: DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
สำหรับข้อมูลดัชนีfor i=0; i<n; i++ สำหรับเนื้อหาที่บันทึกไว้ ให้ทำอย่างใดอย่างหนึ่งต่อไปนี้ตาม RecordStatus::* และกำหนดการภายใน
|
สําหรับข้อมูลดัชนี: ระบุไว้ในเพย์โหลดของเหตุการณ์ สำหรับเนื้อหาที่บันทึกไว้: สตรีม TS ที่รวมแล้วซึ่งกรอกข้อมูลใน FMQ |
TS.TEMI |
ไม่มี | ต้องระบุ:DemuxFilterEvent::DemuxFilterTemiEvent[n] ไม่บังคับ: DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ |
ไม่มี |
MMTP.MMTP |
ไม่มี | ต้องระบุ:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW แนะนำ: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
เรียกใช้Filter.read(buffer, offset, adjustedSize) อย่างน้อย 1 ครั้งตามเหตุการณ์และกำหนดการภายในระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์ |
mmtp ที่กรองออกซึ่งมีส่วนหัว mmtp กรอกใน FMQ |
MMTP.RECORD |
ไม่มี | ต้องระบุ:DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n] RecordStatus::DATA_READY RecordStatus::DATA_OVERFLOW RecordStatus::LOW_WATER RecordStatus::HIGH_WATER ไม่บังคับ: DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
สำหรับข้อมูลดัชนี: for i=0; i<n; i++ สำหรับเนื้อหาที่บันทึกไว้ ให้ทำอย่างใดอย่างหนึ่งต่อไปนี้
RecordStatus::*
|
สําหรับข้อมูลดัชนี: ระบุไว้ในเพย์โหลดของเหตุการณ์ สำหรับเนื้อหาที่บันทึกไว้: สตรีมที่บันทึกไว้ซึ่งมีการรวมข้อมูลใน FMQ หากแหล่งที่มาของตัวกรองสำหรับการบันทึกคือ TLV.TLV ถึง IP.IP ที่มีการส่งผ่าน สตรีมที่บันทึกจะมีส่วนหัว TLV และ IP |
MMTP.DOWNLOAD |
ไม่มี | ต้องระบุ:DemuxFilterEvent::DemuxFilterDownloadEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW ไม่บังคับ: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::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_READY DemuxFilterStatus::DATA_OVERFLOW ไม่บังคับ: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterIpPayloadEvent[i].size) ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์ |
แพ็กเกจเพย์โหลด IP ได้รับการกรอกข้อมูลใน FMQ โดยแพ็กเกจเพย์โหลด IP อื่น |
IP.IP TLV.TLV ALP.ALP |
isPassthrough: |
ไม่บังคับ:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
สตรีมย่อยของโปรโตคอลที่กรองออกจะส่งไปยังตัวกรองถัดไปในเชนตัวกรอง | ไม่มี |
isPassthrough: |
ต้องระบุ:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW แนะนำ: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
เรียกใช้Filter.read(buffer, offset, adjustedSize) อย่างน้อย 1 ครั้งตามเหตุการณ์และกำหนดการภายในระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์ |
กรองสตรีมย่อยของโปรโตคอลที่มีส่วนหัวของโปรโตคอลออกแล้วกรอกข้อมูลใน FMQ | |
IP.PAYLOAD_THROUGH TLV.PAYLOAD_THROUGH ALP.PAYLOAD_THROUGH |
ไม่มี | ไม่บังคับ:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
Payload ของโปรโตคอลที่กรองออกจะส่งไปยังตัวกรองถัดไปในเชนตัวกรอง | ไม่มี |
ตัวอย่างขั้นตอนการใช้ตัวกรองเพื่อสร้าง 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();
กระบวนการ
SectionEvent
FilterCallback 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 ขั้นตอนในการใช้ MediaEvent จากตัวกรอง
- เปิด กำหนดค่า และเริ่มตัวกรอง A/V
- กระบวนการ
MediaEvent
- รับ
MediaEvent
- จัดคิวบล็อกเชิงเส้นไปยัง
codec
- ปล่อยตัวแฮนเดิล A/V เมื่อใช้ข้อมูลแล้ว
Android.media.tv.tuner.dvr
DvrRecorder
มีวิธีการบันทึกเหล่านี้
configure
attachFilter
detachFilter
start
flush
stop
setFileDescriptor
write
DvrPlayback
มีวิธีการเล่นเหล่านี้
configure
start
flush
stop
setFileDescriptor
read
DvrSettings
ใช้เพื่อกําหนดค่า DvrRecorder
และ DvrPlayback
ระบบใช้ OnPlaybackStatusChangedListener
และ OnRecordStatusChangedListener
เพื่อรายงานสถานะของอินสแตนซ์ DVR
ตัวอย่างขั้นตอนในการเริ่มบันทึก
รูปที่ 12 ขั้นตอนในการเริ่มบันทึก
เปิด กำหนดค่า และเริ่ม
DvrRecorder
DvrRecorder 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 ของตัวรับสัญญาณ
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.hal IFrontendCallback.hal |
IDemux |
close |
setFrontendDataSource , openFilter , openDvr , getAvSyncHwId ,
getAvSyncTime , connect / disconnectCiCam |
IDemux.hal |
IDvr |
close , start , stop , configure |
attach/detachFilters , flush , getQueueDesc |
IDvr.hal IDvrCallback.hal |
IFilter |
close , start , stop , configure , getId |
flush , getQueueDesc , releaseAvHandle , setDataSource |
IFilter.hal IFilterCallback.hal |
ILnb |
close , setCallback |
setVoltage , setTone , setSatellitePosition , sendDiseqcMessage |
ILnb.hal ILnbCallback.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 ของ Tuner รองรับการลิงก์ตัวกรองเพื่อให้ลิงก์ตัวกรองกับตัวกรองอื่นๆ สำหรับเลเยอร์หลายเลเยอร์ได้ โดยตัวกรองจะเป็นไปตามกฎด้านล่าง
- ตัวกรองจะลิงก์กันเป็นโครงสร้างต้นไม้ ไม่อนุญาตให้ใช้เส้นทางปิด
- โหนดรากคือ 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 โฟลว์ชาร์ตของการเชื่อมโยงตัวกรองสำหรับเลเยอร์หลายรายการ
เครื่องมือจัดการทรัพยากรของตัวรับสัญญาณ
ก่อนที่จะมีเครื่องมือจัดการทรัพยากรของจูนเนอร์ (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)
/releaseFrontend
requestDemux(TunerDemuxRequest request, int[] demuxHandle)
/releaseDemux
requestDescrambler(TunerDescramblerRequest request, int[] descramblerHandle)
/releaseDescrambler
requestCasSession(CasSessionRequest request, int[] casSessionHandle)
/releaseCasSession
requestLnb(TunerLnbRequest request, int[] lnbHandle)
/releaseLnb
คลาสไคลเอ็นต์และคําขอแสดงอยู่ด้านล่าง
ResourceClientProfile
ResourcesReclaimListener
TunerFrontendRequest
TunerDemuxRequest
TunerDescramblerRequest
CasSessionRequest
TunerLnbRequest
ลำดับความสำคัญของไคลเอ็นต์
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
ค่าลําดับความสําคัญที่กําหนดเองและค่าที่แสดง
TRM มี updateClientPriority
เพื่อให้ไคลเอ็นต์อัปเดตค่าลําดับความสําคัญและค่าที่แสดง
ค่าลําดับความสําคัญที่กําหนดเองจะเขียนทับค่าลําดับความสําคัญที่คํานวณจากประเภท Use Case และรหัสเซสชัน
ค่า nice บ่งบอกถึงความยืดหยุ่นของลักษณะการทํางานของไคลเอ็นต์เมื่อขัดแย้งกับไคลเอ็นต์อื่น ค่าที่เหมาะสมจะลดค่าลําดับความสําคัญของลูกค้าก่อนที่จะเปรียบเทียบค่าลําดับความสําคัญกับลูกค้าที่ท้าทาย
กลไกการเรียกคืน
แผนภาพด้านล่างแสดงวิธีเรียกคืนและกำหนดทรัพยากรเมื่อมีความขัดแย้งเกี่ยวกับทรัพยากร
รูปที่ 15 แผนภาพกลไกการเรียกคืนสำหรับความขัดแย้งระหว่างทรัพยากรของ Tuner