สำหรับ 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: อินเทอร์เฟซระหว่างเฟรมเวิร์กกับแอป
- Tuner Resource Manager (TRM): ทรัพยากร HW ของตัวรับสัญญาณสำหรับพิกัด
สำหรับ Android 11 เราได้ปรับปรุงคอมโพเนนต์ต่อไปนี้แล้ว
- CAS V2
TvInputService
หรือบริการอินพุตทีวี (TIS)TvInputManagerService
หรือบริการโปรแกรมจัดการอินพุตทีวี (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 ที่มีแฮนเดิลหน่วยความจำที่ปลอดภัย
- การแสดงภาพ
การออกแบบโดยรวม
Tuner HAL กำหนดไว้ระหว่างเฟรมเวิร์ก Android และฮาร์ดแวร์ของผู้ให้บริการ
- อธิบายสิ่งที่เฟรมเวิร์กคาดหวังจากผู้ให้บริการและวิธีที่ผู้ให้บริการอาจดำเนินการ
- ส่งออกฟังก์ชันของฟรอนท์เอนด์, Demux และ Descrambler ไปยังเฟรมเวิร์กผ่านอินเทอร์เฟซ
IFrontend
,IDemux
,IDescrambler
,IFilter
,IDvr
และILnb
- รวมฟังก์ชันสำหรับผสานรวม HAL ตัวรับสัญญาณ กับคอมโพเนนต์อื่นๆ ของเฟรมเวิร์ก เช่น
MediaCodec
และAudioTrack
จะมีการสร้างคลาส Java ตัวรับสัญญาณและคลาสเนทีฟ
- Tuner Java API อนุญาตให้แอปเข้าถึง Tuner HAL ผ่าน API สาธารณะ
- คลาสเนทีฟทำให้ควบคุมสิทธิ์และจัดการข้อมูลการบันทึกหรือการเล่นปริมาณมากด้วย HAL ตัวรับสัญญาณ
- โมดูล Native Tuner เป็นสะพานเชื่อมระหว่างคลาส Tuner Java กับ TunerHAL
ระบบจะสร้างคลาส TRM
- จัดการทรัพยากรของตัวรับสัญญาณแบบจำกัด เช่น ฟรอนท์เอนด์, LNB, CAS และอุปกรณ์อินพุตทีวีจาก HAL อินพุตทีวี
- ใช้กฎเพื่อเรียกคืนทรัพยากรที่ไม่เพียงพอจากแอป กฎเริ่มต้นคือโฟกัสอยู่เบื้องหน้าจะชนะ
Media CAS และ CAS HAL ได้รับการปรับปรุงด้วยฟีเจอร์ด้านล่าง
- เปิดเซสชัน CAS สําหรับการใช้งานและอัลกอริทึมที่แตกต่างกัน
- รองรับระบบ CAS แบบไดนามิก เช่น การนำ CICAM ออกและแทรก CICAM
- ผสานรวมกับ HAL ตัวรับสัญญาณโดยการระบุโทเค็นคีย์
MediaCodec
และ AudioTrack
ได้รับการปรับปรุงด้วยฟีเจอร์ด้านล่าง
- ใช้หน่วยความจำ A/V ที่ปลอดภัยเป็นอินพุตเนื้อหา
- กำหนดค่าให้ทำการซิงค์ A/V ของฮาร์ดแวร์ในการเล่นแบบใช้อุโมงค์
- กำหนดค่าการรองรับ
ES_payload
และโหมดการส่งผ่านแล้ว
รูปที่ 2 แผนภาพส่วนประกอบภายใน HAL ของจูนเนอร์
เวิร์กโฟลว์โดยรวม
แผนภาพด้านล่างแสดงลําดับการเรียกใช้สําหรับการเล่นการออกอากาศสด
ตั้งค่า
รูปที่ 3 ลำดับการตั้งค่าสำหรับการเล่นการออกอากาศสด
การจัดการ A/V
รูปที่ 4 การจัดการ A/V สำหรับการเล่นการถ่ายทอดสด
การจัดการเนื้อหาที่มีการสับเปลี่ยน
รูปที่ 5 การจัดการเนื้อหาที่อ่านไม่ได้สำหรับการเล่นการถ่ายทอดสด
กำลังประมวลผลข้อมูล A/V
รูปที่ 6 กำลังประมวลผล A/V สำหรับการถ่ายทอดสด
API ของตัวรับสัญญาณ SDK
Tuner SDK API จะจัดการการโต้ตอบกับ Tuner JNI, Tuner HAL และ TunerResourceManager
แอป TIS ใช้ Tuner SDK API เพื่อเข้าถึงทรัพยากรและคอมโพเนนต์ย่อยของ Tuner เช่น ตัวกรองและโปรแกรมถอดรหัส ฟรอนท์เอนด์และ Deemux เป็นคอมโพเนนต์ภายใน
รูปที่ 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 ใช้แพ็กเกจเพื่อเริ่มต้นและรับอินสแตนซ์ทรัพยากรด้วยการระบุการตั้งค่าเริ่มต้นและ Callback
tuner()
: เริ่มต้นอินสแตนซ์ Tuner โดยระบุพารามิเตอร์useCase
และsessionId
tune()
: รับทรัพยากรฟรอนท์เอนด์และปรับแต่งโดยการระบุพารามิเตอร์FrontendSetting
openFilter()
: รับอินสแตนซ์ตัวกรองโดยระบุประเภทตัวกรองopenDvrRecorder()
: รับอินสแตนซ์การบันทึกโดยระบุขนาดบัฟเฟอร์openDvrPlayback()
: รับอินสแตนซ์การเล่นโดยการระบุขนาดบัฟเฟอร์openDescrambler()
: รับอินสแตนซ์เครื่องมือถอดรหัสopenLnb()
: รับอินสแตนซ์ LNB ภายในopenLnbByName()
: รับอินสแตนซ์ LNB ภายนอกopenTimeFilter()
: รับอินสแตนซ์ตัวกรองเวลา
แพ็กเกจตัวรับสัญญาณมีฟังก์ชันการทำงานที่ไม่ได้อยู่ภายใต้แพ็กเกจตัวกรอง, 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
ในการสแกน 1 ครั้ง และส่ง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 ไปยังบัฟเฟอร์ไคลเอ็นต์ |
แพ็กเกจเซสชันที่ประกอบแล้วหนึ่งแพ็กเกจจะมีการเติม 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 แบบ Muxed ที่ได้รับการตอบสนองเป็น 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 |
กรองฟีดเพย์โหลดโปรโตคอลออกซึ่งตัวกรองถัดไปในสายตัวกรอง | ไม่มี |
ตัวอย่างขั้นตอนการใช้ตัวกรองเพื่อสร้าง 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
โมดูล
ตัวรับสัญญาณ 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 |
ตัวรับสัญญาณ HAL 1.1 (มาจากตัวรับสัญญาณ 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
การเชื่อมโยงตัวกรอง
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)
/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
}
ไฟล์การกำหนดค่า
ไฟล์การกําหนดค่าเริ่มต้น
ไฟล์การกําหนดค่าเริ่มต้นด้านล่างแสดงค่าลําดับความสําคัญสําหรับ Use Case ที่กําหนดไว้ล่วงหน้า ผู้ใช้จะเปลี่ยนค่าได้โดยใช้ไฟล์การกำหนดค่าที่กำหนดเอง
กรณีการใช้งาน | เบื้องหน้า | ฉากหลัง |
---|---|---|
LIVE |
490 | 400 |
PLAYBACK |
480 | 300 |
RECORD |
600 | 500 |
SCAN |
450 | 200 |
BACKGROUND |
180 | 100 |
ไฟล์การกำหนดค่าที่กำหนดเอง
ผู้ให้บริการสามารถปรับแต่งไฟล์การกําหนดค่าได้
/vendor/etc/tunerResourceManagerUseCaseConfig.xml
ไฟล์นี้ใช้เพื่อเพิ่ม นำออก หรืออัปเดตประเภทกรณีการใช้งานและค่าลำดับความสำคัญของกรณีการใช้งาน
ไฟล์ที่กําหนดเองสามารถใช้
platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml
เป็นเทมเพลตได้
ตัวอย่างเช่น Use Case ใหม่ของผู้ให้บริการคือ VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000]
รูปแบบควรเป็นไปตาม platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd
ให้คุณค่าลำดับความสำคัญได้เองและคุ้มราคา
TRM ให้ updateClientPriority
แก่ลูกค้าเพื่ออัปเดตค่าลำดับความสำคัญที่กำหนดเองและมูลค่าที่เหมาะสม
ค่าลําดับความสําคัญที่กําหนดเองจะเขียนทับค่าลําดับความสําคัญที่คํานวณจากประเภท Use Case และรหัสเซสชัน
ค่า nice บ่งบอกถึงความยืดหยุ่นของลักษณะการทํางานของไคลเอ็นต์เมื่อขัดแย้งกับไคลเอ็นต์อื่น ค่าที่เหมาะสมจะลดค่าลําดับความสําคัญของลูกค้าก่อนที่จะเปรียบเทียบค่าลําดับความสําคัญกับลูกค้าที่ท้าทาย
กลไกการเรียกคืน
แผนภาพด้านล่างแสดงวิธีเรียกคืนและกำหนดทรัพยากรเมื่อมีความขัดแย้งเกี่ยวกับทรัพยากร
รูปที่ 15 แผนภาพของกลไกการอ้างสิทธิ์ซ้ำสำหรับความขัดแย้งระหว่างทรัพยากรของตัวรับสัญญาณ