กรอบงานจูนเนอร์

สำหรับ Android 11 หรือสูงกว่า คุณสามารถใช้เฟรมเวิร์ก Android Tuner เพื่อส่งเนื้อหา A/V เฟรมเวิร์กนี้ใช้ไปป์ไลน์ฮาร์ดแวร์จากผู้จำหน่าย ทำให้เหมาะสำหรับ SoC ทั้งระดับล่างและระดับไฮเอนด์ เฟรมเวิร์กให้วิธีการที่ปลอดภัยในการส่งมอบเนื้อหา A/V ที่ได้รับการปกป้องโดยสภาพแวดล้อมการดำเนินการที่เชื่อถือได้ (TEE) และเส้นทางสื่อที่ปลอดภัย (SMP) ทำให้สามารถใช้ในสภาพแวดล้อมการป้องกันเนื้อหาที่มีข้อจำกัดสูง

อินเทอร์เฟซที่เป็นมาตรฐานระหว่าง Tuner และ Android CAS ส่งผลให้มีการผสานรวมที่รวดเร็วยิ่งขึ้นระหว่างผู้จำหน่าย Tuner และผู้ขาย CAS การทำงานของอินเตอร์เฟซจูนเนอร์กับ MediaCodec และ AudioTrack การสร้างวิธีการแก้ปัญหาหนึ่งของโลกสำหรับ Android ทีวี อินเทอร์เฟซจูนเนอร์รองรับทั้งทีวีดิจิตอลและทีวีแอนะล็อกตามมาตรฐานการออกอากาศหลัก

ส่วนประกอบ

สำหรับ Android 11 ส่วนประกอบสามส่วนได้รับการออกแบบมาโดยเฉพาะสำหรับแพลตฟอร์มทีวี

  • จูนเนอร์ฮาล: การเชื่อมต่อระหว่างกรอบและผู้ขาย
  • จูนเนอร์ SDK API: การเชื่อมต่อระหว่างกรอบและปพลิเคชัน
  • ผู้จัดการฝ่ายทรัพยากรจูนเนอร์ (TRM): ทรัพยากรพิกัดจูนเนอร์ดับเบิลยู

สำหรับ 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

Demux รองรับโปรโตคอลสตรีมด้านล่าง

  • กระแสขนส่ง (TS)
  • โปรโตคอลการขนส่งสื่อ MPEG (MMTP)
  • อินเทอร์เน็ตโปรโตคอล (IP)
  • ค่าความยาวประเภท (TLV)
  • โปรโตคอลลิงค์เลเยอร์ ATSC (ALP)

Descrambler รองรับการป้องกันเนื้อหาด้านล่าง

  • เส้นทางสื่อที่ปลอดภัย
  • ล้างเส้นทางสื่อ
  • บันทึกท้องถิ่นที่ปลอดภัย
  • การเล่นในท้องถิ่นที่ปลอดภัย

Tuner API รองรับกรณีการใช้งานด้านล่าง

  • สแกน
  • มีชีวิต
  • การเล่น
  • บันทึก

จูนเนอร์, MediaCodec และ AudioTrack สนับสนุนข้อมูลการไหลของโหมดดังต่อไปนี้

  • ES payload พร้อมบัฟเฟอร์หน่วยความจำที่ชัดเจน
  • เพย์โหลด ES พร้อมที่จับหน่วยความจำที่ปลอดภัย
  • ทะลุผ่าน

การออกแบบโดยรวม

Tuner HAL ถูกกำหนดระหว่างเฟรมเวิร์ก Android และฮาร์ดแวร์ของผู้จำหน่าย

  • อธิบายสิ่งที่กรอบงานคาดหวังจากผู้ขายและวิธีที่ผู้ขายสามารถทำได้
  • การส่งออกฟังก์ชันของส่วนหน้า, demux และ descrambler เพื่อกรอบผ่าน IFrontend , IDemux , IDescrambler , IFilter , IDvr และ ILnb อินเตอร์เฟซ
  • รวมถึงฟังก์ชั่นที่จะบูรณาการจูนเนอร์ฮาลที่มีส่วนประกอบของกรอบอื่น ๆ เช่น MediaCodec และ AudioTrack

มีการสร้างคลาส Tuner Java และคลาสดั้งเดิม

  • Tuner Java API อนุญาตให้แอปเข้าถึง Tuner HAL ผ่าน API สาธารณะ
  • คลาสเนทีฟช่วยให้สามารถควบคุมและจัดการข้อมูลการบันทึกหรือเล่นข้อมูลจำนวนมากด้วย Tuner HAL
  • โมดูล Native Tuner เป็นสะพานเชื่อมระหว่างคลาส Tuner Java และ Tuner HAL

มีการสร้างคลาส TRM

  • จัดการทรัพยากร Tuner ที่จำกัด เช่น Frontend, LNB, เซสชัน CAS และอุปกรณ์อินพุตทีวีจาก HAL อินพุตทีวี
  • ใช้กฎเพื่อเรียกคืนทรัพยากรไม่เพียงพอจากแอป กฎเริ่มต้นคือชัยชนะเบื้องหน้า

สื่อ CAS และ CAS HAL ได้รับการปรับปรุงด้วยคุณสมบัติด้านล่าง

  • เปิดเซสชัน CAS สำหรับการใช้งานและอัลกอริทึมต่างๆ
  • รองรับระบบ CAS แบบไดนามิก เช่น การถอดและการใส่ CICAM
  • ผสานรวมกับ Tuner HAL โดยให้โทเค็นหลัก

MediaCodec และ AudioTrack จะเพิ่มขึ้นกับมีดังต่อไปนี้

  • ใช้หน่วยความจำ A/V ที่ปลอดภัยเป็นอินพุตเนื้อหา
  • กำหนดค่าให้ซิงค์ A/V ของฮาร์ดแวร์ในการเล่นแบบทันเนล
  • สนับสนุนการกำหนดค่าสำหรับ ES_payload และโหมดการส่งผ่าน

การออกแบบโดยรวมของ Tuner HAL

รูปที่ 2 แผนภาพของส่วนประกอบภายในจูนเนอร์ฮาล

เวิร์กโฟลว์โดยรวม

ไดอะแกรมด้านล่างแสดงลำดับการโทรสำหรับการเล่นถ่ายทอดสด

ติดตั้ง

ลำดับการตั้งค่าของไดอะแกรมการเล่นถ่ายทอดสด

รูปลำดับ 3. การติดตั้งสำหรับการเล่นการถ่ายทอดสด

การจัดการ A/V

การจัดการ A/V สำหรับไดอะแกรมการเล่นการถ่ายทอดสด

รูปที่ 4 การจัดการ A / V สำหรับการเล่นการถ่ายทอดสด

การจัดการเนื้อหาที่มีสัญญาณรบกวน

การจัดการเนื้อหาที่มีสัญญาณรบกวนสำหรับไดอะแกรมการเล่นถ่ายทอดสด

รูปที่ 5 การจัดการเนื้อหาตะกายสำหรับการเล่นการถ่ายทอดสด

กำลังประมวลผลข้อมูล A/V

ประมวลผลข้อมูล A/V สำหรับไดอะแกรมการเล่นถ่ายทอดสด

รูปที่ 6 การประมวลผล A / V สำหรับการเล่นการถ่ายทอดสด

จูนเนอร์ SDK API

จูนเนอร์ SDK API จัดการปฏิสัมพันธ์กับจูนเนอร์ JNI ที่จูนเนอร์ฮาลและ TunerResourceManager แอป TIS ใช้ Tuner SDK API เพื่อเข้าถึงทรัพยากร Tuner และส่วนประกอบย่อย เช่น ตัวกรองและตัวถอดรหัส ส่วนหน้าและ demux เป็นส่วนประกอบภายใน

แผนภาพการไหลของ Tuner SDK API

รูปที่ 7 การติดต่อกับจูนเนอร์ SDK API

รุ่น

Tuner SDK API จาก Android 12 รองรับคุณลักษณะใหม่ใน Tuner HAL 1.1 ซึ่งเป็นเวอร์ชันที่เข้ากันได้กับเวอร์ชันก่อนหน้าของ Tuner 1.0

ใช้ API ต่อไปนี้เพื่อตรวจสอบเวอร์ชัน HAL ที่ทำงานอยู่

  • android.media.tv.tuner.TunerVersionChecker.getTunerVersion()

ดูเวอร์ชัน HAL ขั้นต่ำที่จำเป็นได้ในเอกสารประกอบของ Android 12 API ใหม่

แพ็คเกจ

Tuner SDK API มีสี่แพ็คเกจด้านล่าง

  • android.media.tv.tuner
  • android.media.tv.tuner.frontend
  • android.media.tv.tuner.filter
  • android.media.tv.tuner.dvr

แผนภาพการไหลของแพ็คเกจ Tuner SDK API

แพคเกจรูปที่ 8 จูนเนอร์ SDK API

Android.media.tv.tuner

แพ็คเกจ Tuner เป็นจุดเริ่มต้นในการใช้เฟรมเวิร์ก Tuner แอพ TIS ใช้แพ็คเกจเพื่อเริ่มต้นและรับอินสแตนซ์ของทรัพยากรโดยระบุการตั้งค่าเริ่มต้นและการโทรกลับ

  • tuner() : เริ่มต้นอินสแตนซ์จูนเนอร์โดยระบุ useCase และ sessionId พารามิเตอร์
  • tune() : ซื้อทรัพยากรส่วนหน้าและปรับแต่งโดยการระบุ FrontendSetting พารามิเตอร์
  • openFilter() : ซื้อกิจการอินสแตนซ์กรองโดยการระบุชนิดของตัวกรอง
  • openDvrRecorder() : ซื้อกิจการเช่นบันทึกโดยการระบุขนาดของบัฟเฟอร์
  • openDvrPlayback() : ซื้อกิจการเช่นการเล่นโดยการระบุขนาดของบัฟเฟอร์
  • openDescrambler() : ซื้อกิจการอินสแตนซ์ descrambler
  • 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 ฟังเหตุการณ์ที่เกิดขึ้นในส่วนหน้า มาตรฐานของมอกการใช้งานแอพพลิเค ScanCallback การประมวลผลข้อความสแกนจากส่วนหน้า

สแกนช่อง

ในการตั้งค่าทีวี แอปจะสแกนความถี่ที่เป็นไปได้และสร้างรายการช่องเพื่อให้ผู้ใช้เข้าถึงได้ มอกอาจใช้ Tuner.tune , Tuner.scan(BLIND_SCAN) หรือ Tuner.scan(AUTO_SCAN) เพื่อสแกนช่องที่สมบูรณ์

ถ้ามอกมีข้อมูลการจัดส่งที่ถูกต้องสำหรับสัญญาณเช่นความถี่มาตรฐาน (เช่น T / T2, S / S2) และข้อมูลที่จำเป็นเพิ่มเติม (เช่น PLD ID) แล้ว Tuner.tune แนะนำเป็นตัวเลือกที่เร็วขึ้น .

เมื่อผู้ใช้เรียก Tuner.tune การกระทำดังต่อไปนี้เกิดขึ้น:

  • มอก populates FrontendSettings กับข้อมูลที่จำเป็นใช้ Tuner.tune
  • ปรับแต่งรายงาน HAL LOCKED ข้อความหากสัญญาณถูกล็อค
  • มอกใช้ Frontend.getStatus ในการเก็บรวบรวมข้อมูลที่จำเป็น
  • มอก. ย้ายไปยังความถี่ถัดไปที่มีอยู่ในรายการความถี่

มอกเรียก Tuner.tune อีกครั้งจนกว่าความถี่ทั้งหมดถูกใช้จนหมด

ในระหว่างการปรับจูนคุณสามารถเรียก stopTune() หรือ close() เพื่อหยุดหรือยุติการ Tuner.tune โทร

จูนเนอร์.สแกน(AUTO_SCAN)

ถ้ามอกไม่ได้มีข้อมูลเพียงพอที่จะใช้ Tuner.tune แต่มีรายการความถี่และมาตรฐานชนิด (เช่น DVB T / C / S) แล้ว Tuner.scan(AUTO_SCAN) ขอแนะนำ

เมื่อผู้ใช้เรียก Tuner.scan(AUTO_SCAN) การดำเนินการดังต่อไปนี้เกิดขึ้น:

  • มอกใช้ Tuner.scan(AUTO_SCAN) กับ FrontendSettings เต็มไปด้วยความถี่

  • รายงาน HAL สแกน LOCKED ข้อความหากสัญญาณถูกล็อค HAL อาจรายงานข้อความการสแกนอื่นๆ เพื่อให้ข้อมูลเพิ่มเติมเกี่ยวกับสัญญาณ

  • มอกใช้ Frontend.getStatus ข้อมูลที่จำเป็นในการเก็บรวบรวม

  • มอกเรียก Tuner.scan สำหรับ HAL จะยังคงการตั้งค่าต่อไปในความถี่เดียวกัน หาก FrontendSettings โครงสร้างว่างเปล่า HAL ใช้การตั้งค่าที่มีอยู่ต่อไป มิฉะนั้น HAL ใช้ FrontendSettings สำหรับการสแกนเพียงครั้งเดียวและส่ง END เพื่อแสดงให้เห็นว่าการดำเนินการสแกนเสร็จสิ้น

  • มอก. ทำซ้ำการกระทำข้างต้นจนกว่าการตั้งค่าความถี่ทั้งหมดจะหมดลง

  • ฮาลส่ง END เพื่อแสดงให้เห็นว่าการดำเนินการสแกนเสร็จสิ้น

  • มอก. ย้ายไปยังความถี่ถัดไปที่มีอยู่ในรายการความถี่

มอกเรียก Tuner.scan(AUTO_SCAN) อีกครั้งจนกว่าความถี่ทั้งหมดถูกใช้จนหมด

ระหว่างการสแกนคุณสามารถเรียก stopScan() หรือ close() เพื่อหยุดชั่วคราวหรือสิ้นสุดการสแกน

จูนเนอร์.สแกน(BLIND_SCAN)

ถ้ามอกไม่ได้มีรายชื่อความถี่และผู้ขาย HAL สามารถค้นหาความถี่ของส่วนหน้าของผู้ใช้กำหนดที่จะได้รับทรัพยากรส่วนหน้าแล้ว Tuner.scan(BLIND_SCAN) ขอแนะนำ

  • มอกใช้ Tuner.scan(BLIND_SCAN) ความถี่สามารถระบุได้ใน FrontendSettings ความถี่เริ่มต้น แต่มอกละเว้นการตั้งค่าอื่น ๆ ใน FrontendSettings
  • ฮาลรายงานสแกน LOCKED ข้อความหากสัญญาณถูกล็อค
  • มอกใช้ Frontend.getStatus ข้อมูลที่จำเป็นในการเก็บรวบรวม
  • มอกเรียก Tuner.scan อีกครั้งเพื่อดำเนินการสแกน ( FrontendSettings จะถูกละเว้น.)
  • มอก. ทำซ้ำการกระทำข้างต้นจนกว่าการตั้งค่าความถี่ทั้งหมดจะหมดลง HAL เพิ่มความถี่โดยไม่ต้องดำเนินการใดๆ จาก มอก. ฮาลรายงาน PROGRESS

มอกเรียก Tuner.scan(AUTO_SCAN) อีกครั้งจนกว่าความถี่ทั้งหมดถูกใช้จนหมด ฮาลรายงาน END เพื่อแสดงให้เห็นว่าการดำเนินการสแกนเสร็จสิ้น

ระหว่างการสแกนคุณสามารถเรียก stopScan() หรือ close() เพื่อหยุดชั่วคราวหรือสิ้นสุดการสแกน

แผนภาพการไหลของกระบวนการสแกน มอก.

แผนภาพรูปที่ 9 การไหลของสแกนมอก

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:
true
บังคับ:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

ที่แนะนำ:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
ตามงานและกำหนดการภายในรัน
Filter.read(buffer, offset, adjustedSize) หนึ่งครั้งหรือมากกว่า

ข้อมูลถูกคัดลอกจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
แพ็คเกจเซสชันที่ประกอบเข้าด้วยกันจะถูกเติมใน FMQ โดยแพ็คเกจเซสชันอื่น
isRaw:
false
บังคับ:
DemuxFilterEvent::DemuxFilterSectionEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

ไม่จำเป็น:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterSectionEven[i].size)


ข้อมูลถูกคัดลอกจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
TS.PES isRaw:
true
บังคับ:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

ที่แนะนำ:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
ตามงานและกำหนดการภายในรัน
Filter.read(buffer, offset, adjustedSize) หนึ่งครั้งหรือมากกว่า

ข้อมูลถูกคัดลอกจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
แพ็คเกจ PES ที่ประกอบแล้วหนึ่งชุดจะถูกเติมใน FMQ โดยแพ็คเกจ PES อื่น
isRaw:
false
บังคับ:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

ไม่จำเป็น:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterPesEven[i].size)


ข้อมูลถูกคัดลอกจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
MMTP.PES isRaw:
true
บังคับ:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

ที่แนะนำ:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
ตามงานและกำหนดการภายในรัน
Filter.read(buffer, offset, adjustedSize) หนึ่งครั้งหรือมากกว่า

ข้อมูลถูกคัดลอกจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
แพ็คเกจ MFU ที่ประกอบแล้วหนึ่งชุดจะถูกเติมใน FMQ โดยแพ็คเกจ MFU อื่น
isRaw:
false
บังคับ:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

ไม่จำเป็น:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterPesEven[i].size)


ข้อมูลถูกคัดลอกจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
TS.TS
ไม่มี บังคับ:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

ที่แนะนำ:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
ตามงานและกำหนดการภายในรัน
Filter.read(buffer, offset, adjustedSize) หนึ่งครั้งหรือมากกว่า

ข้อมูลถูกคัดลอกจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
กรองออก ts กับ ts ส่วนหัว
ถูกกรอกใน FMQ
TS.Audio
TS.Video
MMTP.Audio
MMTP.Video
isPassthrough:
true
ไม่จำเป็น:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
ลูกค้าสามารถเริ่มต้น MediaCodec หลังจากที่ได้รับ DemuxFilterStatus::DATA_READY
ลูกค้าสามารถโทร Filter.flush หลังจากที่ได้รับ DemuxFilterStatus::DATA_OVERFLOW
ไม่มี
isPassthrough:
false
บังคับ:
DemuxFilterEvent::DemuxFilterMediaEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

ไม่จำเป็น:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
หากต้องการใช้ MediaCodec :
for i=0; i<n; i++
linearblock = MediaEvent[i].getLinearBlock();
codec.startQueueLinearBlock(linearblock)
linearblock.recycle()


หากต้องการใช้เสียงโดยตรง AudioTrack :
for i=0; i<n; i++
audioHandle = MediaEvent[i].getAudioHandle();
audiotrack.write(encapsulated(audiohandle))
ข้อมูล ES หรือ ES บางส่วนในหน่วยความจำ ION
TS.PCR
IP.NTP
ALP.PTP
ไม่มี บังคับ: N / A
ตัวเลือก: N / A
ไม่มี ไม่มี
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++
DemuxFilterTsRecordEvent[i];


สำหรับเนื้อหาที่บันทึกไว้ตาม RecordStatus::* และกำหนดการภายในอย่างใดอย่างหนึ่งต่อไปนี้:
  • เรียก DvrRecord.write(adustedSize) หนึ่งครั้งหรือมากกว่าในการจัดเก็บข้อมูล
    ข้อมูลจะถูกโอนจาก MQ ของ HAL ไปยังที่จัดเก็บ
  • เรียก DvrRecord.write(buffer, adustedSize) หนึ่งครั้งหรือมากกว่าบัฟเฟอร์
    ข้อมูลถูกคัดลอกจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
สำหรับข้อมูลดัชนี: ดำเนินการในส่วนของข้อมูลเหตุการณ์

สำหรับเนื้อหาที่บันทึก: มักซ์ 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++
DemuxFilterTemiEvent[i];
ไม่มี
MMTP.MMTP ไม่มี บังคับ:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

ที่แนะนำ:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
ตามงานและกำหนดการภายในรัน
Filter.read(buffer, offset, adjustedSize) หนึ่งครั้งหรือมากกว่า

ข้อมูลถูกคัดลอกจาก 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++
DemuxFilterMmtpRecordEvent[i];


สำหรับเนื้อหาที่บันทึกไว้ตาม RecordStatus::* และกำหนดการภายในอย่างใดอย่างหนึ่งต่อไปนี้:
  • เรียก DvrRecord.write(adjustedSize) หนึ่งครั้งหรือมากกว่าในการจัดเก็บข้อมูล
    ข้อมูลจะถูกโอนจาก MQ ของ HAL ไปยังที่จัดเก็บ
  • เรียก DvrRecord.write(buffer, adjustedSize) หนึ่งครั้งหรือมากกว่าบัฟเฟอร์
    ข้อมูลถูกคัดลอกจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
สำหรับข้อมูลดัชนี: ดำเนินการในส่วนของข้อมูลเหตุการณ์

สำหรับเนื้อหาที่บันทึก: มักซ์กระแสบันทึกเติมเต็มใน 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:
true
ไม่จำเป็น:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
สตรีมย่อยของโปรโตคอลที่ถูกกรองออกจะดึงตัวกรองถัดไปในสายโซ่ตัวกรอง ไม่มี
isPassthrough:
false
บังคับ:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

ที่แนะนำ:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
ตามงานและกำหนดการภายในรัน
Filter.read(buffer, offset, adjustedSize) หนึ่งครั้งหรือมากกว่า

ข้อมูลถูกคัดลอกจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
สตรีมย่อยของโปรโตคอลที่กรองออกพร้อมส่วนหัวของโปรโตคอลจะถูกกรอกใน FMQ
IP.PAYLOAD_THROUGH
TLV.PAYLOAD_THROUGH
ALP.PAYLOAD_THROUGH
ไม่มี ไม่จำเป็น:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
เพย์โหลดโปรโตคอลที่ถูกกรองออกจะป้อนตัวกรองถัดไปในสายโซ่ตัวกรอง ไม่มี
ตัวอย่างโฟลว์การใช้ตัวกรองเพื่อสร้าง PSI/SI

ตัวอย่างโฟลว์สำหรับการใช้ตัวกรองเพื่อสร้าง PSI/SI

รูปที่ 10 เพื่อสร้างกระแส PSI / SI

  1. เปิดตัวกรอง

    Filter filter = tuner.openFilter(
      Filter.TYPE_TS,
      Filter.SUBTYPE_SECTION,
      /* bufferSize */1000,
      executor,
      filterCallback
    );
    
  2. กำหนดค่าและเริ่มตัวกรอง

    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();
    
  3. กระบวนการ 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 จาก filter

ตัวอย่างขั้นตอนการใช้ MediaEvent จากตัวกรอง

รูปที่ 11 การไหลของการใช้ MediaEvent จากตัวกรอง

  1. เปิด กำหนดค่า และเริ่มตัวกรอง A/V
  2. กระบวนการ MediaEvent
  3. รับ MediaEvent
  4. คิวบล็อกเส้น codec
  5. ปล่อยที่จับ 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 การไหลที่จะเริ่มต้นการบันทึก

  1. เปิดการกำหนดค่าและเริ่มต้น 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();
    
  2. รับ 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. }
          }
        }
    };
    
  3. เตรียม 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

โมดูล

จูนเนอร์ 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

แผนภาพการไหลของการโต้ตอบระหว่างโมดูลของ Tuner 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

ก่อน Tuner Resource Manager (TRM) การสลับระหว่างสองแอพต้องใช้ฮาร์ดแวร์ Tuner เดียวกัน TV Input Framework (TIF) ใช้กลไก "ก่อนได้รับชัยชนะ" ซึ่งหมายความว่าแอปใดก็ตามที่ได้รับทรัพยากรก่อนจะเก็บทรัพยากรไว้ อย่างไรก็ตาม กลไกนี้อาจไม่เหมาะสำหรับกรณีการใช้งานที่ซับซ้อนบางอย่าง

TRM ทำงานเป็นบริการระบบการจัดการจูนเนอร์, TVInput และ CAS ทรัพยากรฮาร์ดแวร์สำหรับปพลิเคชัน TRM ใช้กลไก "การชนะเบื้องหน้า" ซึ่งคำนวณลำดับความสำคัญของแอปตามสถานะเบื้องหน้าหรือเบื้องหลังของแอป และประเภทกรณีใช้ TRM ให้หรือเพิกถอนทรัพยากรตามลำดับความสำคัญ TRM รวมศูนย์การจัดการทรัพยากรรถเอทีวีสำหรับการออกอากาศ OTT และ DVR

อินเทอร์เฟซ TRM

TRM exposes AIDL อินเตอร์เฟซใน ITunerResourceManager.aidl กรอบจูนเนอร์ที่ 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 ดึงกระบวนการ ID จาก mTvInputSessionId ที่จะตัดสินใจว่าแอปเป็นเบื้องหน้าหรือพื้นหลังของแอป เพื่อสร้าง mTvInputSessionId , TvInputService.onCreateSession หรือ TvInputService.onCreateRecordingSession เริ่มต้นเซสชั่นมอก

mUseCase บ่งชี้กรณีการใช้งานเซสชั่นของ กรณีการใช้งานที่กำหนดไว้ล่วงหน้ามีการระบุไว้ด้านล่าง

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 ไฟล์นี้ใช้เพื่อเพิ่ม ลบ หรืออัพเดตชนิดเคสการใช้งานและค่าลำดับความสำคัญของเคสการใช้งาน ไฟล์ที่กำหนดเองสามารถใช้ 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 สำหรับลูกค้าในการปรับปรุงค่าลำดับความสำคัญโดยพลการและความคุ้มค่าที่ดี ค่าลำดับความสำคัญตามอำเภอใจจะเขียนทับค่าลำดับความสำคัญที่คำนวณจากประเภทกรณีการใช้งานและ ID เซสชัน

ค่าที่ดีบ่งชี้ว่าพฤติกรรมของลูกค้าผ่อนปรนเพียงใดเมื่อขัดแย้งกับลูกค้ารายอื่น ค่าที่ดีจะลดค่าลำดับความสำคัญของไคลเอ็นต์ก่อนที่จะเปรียบเทียบกับค่าลำดับความสำคัญกับไคลเอ็นต์ที่ท้าทาย

กลไกการเรียกคืน

ไดอะแกรมด้านล่างแสดงวิธีการเรียกคืนและกำหนดทรัพยากรเมื่อเกิดความขัดแย้งของทรัพยากร

ไดอะแกรมของกระบวนการกลไกการเรียกคืน

รูปที่ 15 แผนผังของกลไกการเรียกคืนสำหรับความขัดแย้งระหว่างทรัพยากรจูนเนอร์