Khung bộ dò

Đối với Android 11 trở lên, bạn có thể sử dụng khung Android Tuner để phân phối nội dung A/V. Khung này sử dụng hệ thống phần cứng từ các nhà cung cấp, làm cho nó phù hợp với cả SoC cấp thấp và cao cấp. Khung này cung cấp một cách an toàn để phân phối nội dung A/V được bảo vệ bởi môi trường thực thi đáng tin cậy (TEE) và đường dẫn phương tiện an toàn (SMP), cho phép sử dụng nó trong môi trường bảo vệ nội dung, bị hạn chế cao.

Giao diện được tiêu chuẩn hóa giữa Tuner và Android CAS mang lại sự tích hợp nhanh hơn giữa nhà cung cấp Tuner và nhà cung cấp CAS. Giao diện Tuner hoạt động với MediaCodecAudioTrack để xây dựng giải pháp toàn cầu cho Android TV. Giao diện Tuner hỗ trợ cả TV kỹ thuật số và TV analog dựa trên các tiêu chuẩn phát sóng chính.

Các thành phần

Đối với Android 11, ba thành phần được thiết kế riêng cho nền tảng TV.

  • Tuner HAL: Giao diện giữa khung và nhà cung cấp
  • API Tuner SDK: Giao diện giữa khung và ứng dụng
  • Trình quản lý tài nguyên bộ điều chỉnh (TRM): Tọa độ các tài nguyên CTNH của bộ điều chỉnh

Đối với Android 11, các thành phần sau đã được cải tiến.

  • CAS V2
  • TvInputService hoặc Dịch vụ đầu vào TV (TIS)
  • TvInputManagerService hoặc Dịch vụ quản lý đầu vào TV (TIMS)
  • MediaCodec hoặc codec phương tiện
  • AudioTrack hoặc bản âm thanh
  • MediaResourceManager hoặc trình quản lý tài nguyên phương tiện (MRM)

Sơ đồ dòng chảy của các thành phần khung Tuner.

Hình 1. Tương tác giữa các thành phần Android TV

Đặc trưng

Frontend hỗ trợ các tiêu chuẩn DTV bên dưới.

  • ATSC
  • ATSC3
  • DVB C/S/T
  • ISDB S/S3/T
  • Tương tự

Giao diện người dùng trong Android 12 có Tuner HAL 1.1 trở lên hỗ trợ chuẩn DTV bên dưới.

  • DTMB

Demux hỗ trợ các giao thức truyền phát bên dưới.

  • Luồng vận chuyển (TS)
  • Giao thức truyền tải phương tiện MPEG (MMTP)
  • Giao thức Internet (IP)
  • Giá trị độ dài loại (TLV)
  • Giao thức lớp liên kết ATSC (ALP)

Descrambler hỗ trợ các biện pháp bảo vệ nội dung bên dưới.

  • Đường dẫn phương tiện an toàn
  • Xóa đường dẫn phương tiện
  • Bảo mật hồ sơ địa phương
  • Phát lại cục bộ an toàn

API bộ điều chỉnh hỗ trợ các trường hợp sử dụng bên dưới.

  • Quét
  • Sống
  • Phát lại
  • Ghi

Tuner, MediaCodecAudioTrack hỗ trợ các chế độ luồng dữ liệu bên dưới.

  • Tải trọng ES với bộ nhớ đệm rõ ràng
  • Tải trọng ES có bộ nhớ an toàn
  • Truyền qua

Thiết kế tổng thể

Tuner HAL được xác định giữa khung Android và phần cứng của nhà cung cấp.

  • Mô tả những gì framework mong đợi từ nhà cung cấp và cách nhà cung cấp có thể thực hiện điều đó.
  • Xuất các chức năng của giao diện người dùng, demux và descrambler sang khung thông qua các giao diện IFrontend , IDemux , IDescrambler , IFilter , IDvrILnb .
  • Bao gồm các chức năng để tích hợp Tuner HAL với các thành phần khung khác, chẳng hạn như MediaCodecAudioTrack .

Một lớp Java Tuner và lớp gốc được tạo.

  • API Tuner Java cho phép các ứng dụng truy cập Tuner HAL thông qua các API công khai.
  • Lớp gốc cho phép kiểm soát quyền và xử lý lượng lớn dữ liệu ghi hoặc phát lại bằng Tuner HAL.
  • Mô-đun Tuner gốc là cầu nối giữa lớp Tuner Java và Tuner HAL.

Một lớp TRM được tạo.

  • Quản lý các tài nguyên Bộ điều chỉnh có giới hạn, chẳng hạn như các phiên Frontend, LNB, CAS và thiết bị đầu vào TV từ HAL đầu vào TV.
  • Áp dụng các quy tắc để lấy lại tài nguyên không đủ từ ứng dụng. Quy tắc mặc định là chiến thắng ở tiền cảnh.

Media CAS và CAS HAL được cải tiến với các tính năng bên dưới.

  • Mở các phiên CAS cho các cách sử dụng và thuật toán khác nhau.
  • Hỗ trợ các hệ thống CAS động, chẳng hạn như loại bỏ và chèn CICAM.
  • Tích hợp với Tuner HAL bằng cách cung cấp mã thông báo chính.

MediaCodecAudioTrack được cải tiến với các tính năng bên dưới.

  • Lấy bộ nhớ A/V an toàn làm đầu vào nội dung.
  • Được định cấu hình để thực hiện đồng bộ hóa A/V phần cứng khi phát lại theo đường hầm.
  • Hỗ trợ được định cấu hình cho ES_payload và chế độ chuyển tiếp.

Thiết kế tổng thể của Tuner HAL.

Hình 2. Sơ đồ các thành phần trong Tuner HAL

Quy trình làm việc tổng thể

Các sơ đồ bên dưới minh họa trình tự cuộc gọi để phát lại chương trình phát sóng trực tiếp.

Cài đặt

Trình tự thiết lập sơ đồ phát sóng trực tiếp.

Hình 3. Trình tự thiết lập để phát lại chương trình phát sóng trực tiếp

Xử lý A/V

Xử lý A/V cho sơ đồ phát lại chương trình phát sóng trực tiếp.

Hình 4. Xử lý A/V để phát lại chương trình phát sóng trực tiếp

Xử lý nội dung bị xáo trộn

Xử lý nội dung bị xáo trộn cho sơ đồ phát lại chương trình phát sóng trực tiếp.

Hình 5. Xử lý nội dung bị xáo trộn để phát lại chương trình phát sóng trực tiếp

Xử lý dữ liệu A/V

Xử lý dữ liệu A/V cho sơ đồ phát lại chương trình phát sóng trực tiếp.

Hình 6. Xử lý A/V để phát lại chương trình phát sóng trực tiếp

API SDK điều chỉnh

API Tuner SDK xử lý các tương tác với Tuner JNI, Tuner HAL và TunerResourceManager . Ứng dụng TIS sử dụng API Tuner SDK để truy cập các tài nguyên và thành phần phụ của Tuner như bộ lọc và bộ giải mã. Frontend và demux là các thành phần bên trong.

Sơ đồ quy trình của Tuner SDK API.

Hình 7. Tương tác với API Tuner SDK

Phiên bản

Từ Android 12, API Tuner SDK hỗ trợ tính năng mới trong Tuner HAL 1.1, đây là phiên bản nâng cấp tương thích ngược của Tuner 1.0.

Sử dụng API sau để kiểm tra phiên bản HAL đang chạy.

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

Bạn có thể tìm thấy phiên bản HAL yêu cầu tối thiểu trong tài liệu về API Android 12 mới.

Gói

API Tuner SDK cung cấp bốn gói bên dưới.

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

Sơ đồ quy trình của các gói API Tuner SDK.

Hình 8. Các gói API Tuner SDK

Android.media.tv.tuner

Gói Tuner là điểm bắt đầu để sử dụng khung Tuner. Ứng dụng TIS sử dụng gói để khởi tạo và thu thập các phiên bản tài nguyên bằng cách chỉ định cài đặt ban đầu và gọi lại.

  • tuner() : Khởi tạo một phiên bản Tuner bằng cách chỉ định các tham số useCasesessionId .
  • tune() : Thu thập tài nguyên giao diện người dùng và điều chỉnh bằng cách chỉ định tham số FrontendSetting .
  • openFilter() : Lấy một phiên bản bộ lọc bằng cách chỉ định loại bộ lọc.
  • openDvrRecorder() : Lấy phiên bản ghi bằng cách chỉ định kích thước bộ đệm.
  • openDvrPlayback() : Lấy phiên bản phát lại bằng cách chỉ định kích thước bộ đệm.
  • openDescrambler() : Thu thập một phiên bản descrambler.
  • openLnb() : Thu thập một phiên bản LNB nội bộ.
  • openLnbByName() : Thu thập một phiên bản LNB bên ngoài.
  • openTimeFilter() : Lấy phiên bản bộ lọc thời gian.

Gói Tuner cung cấp các chức năng không có trong các gói bộ lọc, DVR và giao diện người dùng. Các chức năng được liệt kê dưới đây.

  • cancelTuning
  • scan / cancelScanning
  • getAvSyncHwId
  • getAvSyncTime
  • connectCiCam1 / disconnectCiCam
  • shareFrontendFromTuner
  • updateResourcePriority
  • setOnTuneEventListener
  • setResourceLostListener

Android.media.tv.tuner.frontend

Gói giao diện người dùng bao gồm các bộ sưu tập cài đặt, thông tin, trạng thái, sự kiện và khả năng liên quan đến giao diện người dùng.

Các lớp học

FrontendSettings được lấy từ các tiêu chuẩn DTV khác nhau theo các lớp bên dưới.

  • AnalogFrontendSettings
  • Atsc3FrontendSettings
  • AtscFrontendSettings
  • DvbcFrontendSettings
  • DvbsFrontendSettings
  • DvbtFrontendSettings
  • Isdbs3FrontendSettings
  • IsdbsFrontendSettings
  • IsdbtFrontendSettings

Từ Android 12 với Tuner HAL 1.1 trở lên, chuẩn DTV sau được hỗ trợ.

  • DtmbFrontendSettings

FrontendCapabilities được bắt nguồn từ các tiêu chuẩn DTV khác nhau theo các lớp bên dưới.

  • AnalogFrontendCapabilities
  • Atsc3FrontendCapabilities
  • AtscFrontendCapabilities
  • DvbcFrontendCapabilities
  • DvbsFrontendCapabilities
  • DvbtFrontendCapabilities
  • Isdbs3FrontendCapabilities
  • IsdbsFrontendCapabilities
  • IsdbtFrontendCapabilities

Từ Android 12 với Tuner HAL 1.1 trở lên, chuẩn DTV sau được hỗ trợ.

  • DtmbFrontendCapabilities

FrontendInfo lấy thông tin của giao diện người dùng. FrontendStatus truy xuất trạng thái hiện tại của giao diện người dùng. OnTuneEventListener lắng nghe các sự kiện ở giao diện người dùng. Ứng dụng TIS sử dụng ScanCallback để xử lý tin nhắn quét từ giao diện người dùng.

Quét kênh

Để thiết lập TV, ứng dụng sẽ quét các tần số có thể có và xây dựng danh sách kênh để người dùng truy cập. TIS có thể sử dụng Tuner.tune , Tuner.scan(BLIND_SCAN) hoặc Tuner.scan(AUTO_SCAN) để hoàn tất quá trình quét kênh.

Nếu TIS có thông tin phân phối chính xác cho tín hiệu, chẳng hạn như tần số, tiêu chuẩn (ví dụ: T/T2, S/S2) và thông tin cần thiết bổ sung (ví dụ: ID PLD), thì Tuner.tune được khuyến nghị là tùy chọn nhanh hơn .

Khi người dùng gọi Tuner.tune , các hành động sau sẽ xảy ra:

  • TIS điền thông tin bắt buộc vào FrontendSettings bằng cách sử dụng Tuner.tune .
  • Báo cáo HAL điều chỉnh các tin nhắn LOCKED nếu tín hiệu bị khóa.
  • TIS sử dụng Frontend.getStatus để thu thập thông tin cần thiết.
  • TIS chuyển sang tần số khả dụng tiếp theo trong danh sách tần số của nó.

TIS gọi lại Tuner.tune cho đến khi hết tần số.

Trong khi điều chỉnh, bạn có thể gọi stopTune() hoặc close() để tạm dừng hoặc kết thúc cuộc gọi Tuner.tune .

Tuner.scan(AUTO_SCAN)

Nếu TIS không có đủ thông tin để sử dụng Tuner.tune nhưng có danh sách tần số và loại tiêu chuẩn (ví dụ: DVB T/C/S), thì nên sử dụng Tuner.scan(AUTO_SCAN) .

Khi người dùng gọi Tuner.scan(AUTO_SCAN) , các hành động sau sẽ xảy ra:

  • TIS sử dụng Tuner.scan(AUTO_SCAN) với FrontendSettings chứa đầy tần số.

  • Báo cáo HAL quét các tin nhắn LOCKED nếu tín hiệu bị khóa. HAL cũng có thể báo cáo các thông báo quét khác để cung cấp thêm thông tin về tín hiệu.

  • TIS sử dụng Frontend.getStatus để thu thập thông tin cần thiết.

  • TIS gọi Tuner.scan để HAL tiếp tục cài đặt tiếp theo trên cùng tần số. Nếu cấu trúc FrontendSettings trống, HAL sẽ sử dụng cài đặt có sẵn tiếp theo. Mặt khác, HAL sử dụng FrontendSettings để quét một lần và gửi END để cho biết rằng thao tác quét đã kết thúc.

  • TIS lặp lại các hành động trên cho đến khi hết tất cả cài đặt về tần số.

  • HAL gửi END để cho biết quá trình quét đã kết thúc.

  • TIS chuyển sang tần số khả dụng tiếp theo trong danh sách tần số của nó.

TIS gọi lại Tuner.scan(AUTO_SCAN) cho đến khi hết tần số.

Trong quá trình quét, bạn có thể gọi stopScan() hoặc close() để tạm dừng hoặc kết thúc quá trình quét.

Tuner.scan(BLIND_SCAN)

Nếu TIS không có danh sách tần số và HAL của nhà cung cấp có thể tìm kiếm tần số của giao diện người dùng do người dùng chỉ định để lấy tài nguyên giao diện người dùng, thì nên sử dụng Tuner.scan(BLIND_SCAN) .

  • TIS sử dụng Tuner.scan(BLIND_SCAN) . Một tần số có thể được chỉ định trong FrontendSettings cho tần số bắt đầu, nhưng TIS bỏ qua các cài đặt khác trong FrontendSettings .
  • HAL báo cáo thông báo KHÓA LOCKED nếu tín hiệu bị khóa.
  • TIS sử dụng Frontend.getStatus để thu thập thông tin cần thiết.
  • TIS gọi lại Tuner.scan để tiếp tục quét. ( FrontendSettings bị bỏ qua.)
  • TIS lặp lại các hành động trên cho đến khi hết tất cả cài đặt về tần số. Tần số tăng HAL mà không cần thực hiện hành động nào từ TIS. HAL báo cáo PROGRESS .

TIS gọi lại Tuner.scan(AUTO_SCAN) cho đến khi hết tần số. HAL báo cáo END để cho biết rằng thao tác quét đã kết thúc.

Trong quá trình quét, bạn có thể gọi stopScan() hoặc close() để tạm dừng hoặc kết thúc quá trình quét.

Sơ đồ quy trình của quá trình TIS Scan.

Hình 9. Sơ đồ quy trình quét TIS

Android.media.tv.tuner.filter

Gói bộ lọc là tập hợp các hoạt động lọc cùng với cấu hình, cài đặt, lệnh gọi lại và sự kiện. Gói này bao gồm các hoạt động dưới đây. Tham khảo mã nguồn Android để biết danh sách đầy đủ các hoạt động.

  • configure()
  • start()
  • stop()
  • flush()
  • read()

Tham khảo mã nguồn Android để biết danh sách đầy đủ.

FilterConfiguration có nguồn gốc từ các lớp bên dưới. Các cấu hình dành cho loại bộ lọc chính và chúng chỉ định giao thức nào bộ lọc sử dụng để trích xuất dữ liệu.

  • AlpFilterConfiguration
  • IpFilterConfiguration
  • MmtpFilterConfiguration
  • TlvFilterConfiguration
  • TsFilterConfiguration

Các cài đặt được bắt nguồn từ các lớp bên dưới. Cài đặt dành cho loại bộ lọc phụ và chúng chỉ định loại dữ liệu mà bộ lọc có thể loại trừ.

  • SectionSettings
  • AvSettings
  • PesSettings
  • RecordSettings
  • DownloadSettings

FilterEvent được lấy từ các lớp bên dưới để báo cáo các sự kiện cho các loại dữ liệu khác nhau.

  • SectionEvent
  • MediaEvent
  • PesEvent
  • TsRecordEvent
  • MmtpRecordEvent
  • TemiEvent
  • DownloadEvent
  • IpPayloadEvent

Từ Android 12 có Tuner HAL 1.1 trở lên, các sự kiện sau được hỗ trợ.

  • IpCidChangeEvent
  • RestartEvent
  • ScramblingStatusEvent
Sự kiện và định dạng dữ liệu từ bộ lọc
Tuýt lọc Cờ Sự kiện Thao tác dữ liệu Định dạng dữ liệu
TS.SECTION
MMTP.SECTION
IP.SECTION
TLV.SECTION
ALP.SECTION
isRaw:
true
Bắt buộc:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Khuyến khích:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Theo sự kiện và lịch trình nội bộ, chạy
Filter.read(buffer, offset, adjustedSize) một hoặc nhiều lần.

Dữ liệu được sao chép từ MQ của HAL vào bộ đệm máy khách.
Một gói phiên đã lắp ráp được điền vào FMQ bằng một gói phiên khác.
isRaw:
false
Bắt buộc:
DemuxFilterEvent::DemuxFilterSectionEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Không bắt buộc:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterSectionEven[i].size)


Dữ liệu được sao chép từ MQ của HAL vào bộ đệm máy khách.
TS.PES isRaw:
true
Bắt buộc:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Khuyến khích:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Theo sự kiện và lịch trình nội bộ, chạy
Filter.read(buffer, offset, adjustedSize) một hoặc nhiều lần.

Dữ liệu được sao chép từ MQ của HAL vào bộ đệm máy khách.
Một gói PES đã lắp ráp sẽ được điền vào FMQ bằng một gói PES khác.
isRaw:
false
Bắt buộc:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Không bắt buộc:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterPesEven[i].size)


Dữ liệu được sao chép từ MQ của HAL vào bộ đệm máy khách.
MMTP.PES isRaw:
true
Bắt buộc:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Khuyến khích:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Theo sự kiện và lịch trình nội bộ, chạy
Filter.read(buffer, offset, adjustedSize) một hoặc nhiều lần.

Dữ liệu được sao chép từ MQ của HAL vào bộ đệm máy khách.
Một gói MFU đã lắp ráp được điền vào FMQ bằng một gói MFU khác.
isRaw:
false
Bắt buộc:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Không bắt buộc:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterPesEven[i].size)


Dữ liệu được sao chép từ MQ của HAL vào bộ đệm máy khách.
TS.TS
không áp dụng Bắt buộc:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Khuyến khích:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Theo sự kiện và lịch trình nội bộ, chạy
Filter.read(buffer, offset, adjustedSize) một hoặc nhiều lần.

Dữ liệu được sao chép từ MQ của HAL vào bộ đệm máy khách.
Đã lọc ts với tiêu đề ts
được điền vào FMQ.
TS.Audio
TS.Video
MMTP.Audio
MMTP.Video
isPassthrough:
true
Không bắt buộc:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Máy khách có thể khởi động MediaCodec sau khi nhận được DemuxFilterStatus::DATA_READY .
Máy khách có thể gọi Filter.flush sau khi nhận được DemuxFilterStatus::DATA_OVERFLOW .
không áp dụng
isPassthrough:
false
Bắt buộc:
DemuxFilterEvent::DemuxFilterMediaEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Không bắt buộc:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Để sử dụng MediaCodec :
for i=0; i<n; i++
linearblock = MediaEvent[i].getLinearBlock();
codec.startQueueLinearBlock(linearblock)
linearblock.recycle()


Để sử dụng Âm thanh trực tiếp của AudioTrack :
for i=0; i<n; i++
audioHandle = MediaEvent[i].getAudioHandle();
audiotrack.write(encapsulated(audiohandle))
ES hoặc dữ liệu ES một phần trong bộ nhớ ION.
TS.PCR
IP.NTP
ALP.PTP
không áp dụng Bắt buộc: Không áp dụng
Tùy chọn: Không áp dụng
không áp dụng không áp dụng
TS.RECORD không áp dụng Bắt buộc:
DemuxFilterEvent::DemuxFilterTsRecordEvent[n]
RecordStatus::DATA_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

Không bắt buộc:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Đối với dữ liệu chỉ mục:
for i=0; i<n; i++
DemuxFilterTsRecordEvent[i];


Đối với nội dung đã ghi , theo RecordStatus::* và lịch trình nội bộ, hãy thực hiện một trong các thao tác sau:
  • Chạy DvrRecord.write(adustedSize) một hoặc nhiều lần vào bộ nhớ.
    Dữ liệu được chuyển từ MQ của HAL sang bộ lưu trữ.
  • Chạy DvrRecord.write(buffer, adustedSize) một hoặc nhiều lần để đệm.
    Dữ liệu được sao chép từ MQ của HAL sang bộ đệm máy khách.
Đối với dữ liệu chỉ mục: Được mang trong tải trọng sự kiện.

Đối với nội dung được ghi: Luồng TS trộn lẫn được điền vào FMQ.
TS.TEMI không áp dụng Bắt buộc:
DemuxFilterEvent::DemuxFilterTemiEvent[n]

Không bắt buộc:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
DemuxFilterTemiEvent[i];
không áp dụng
MMTP.MMTP không áp dụng Bắt buộc:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Khuyến khích:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Theo sự kiện và lịch trình nội bộ, chạy
Filter.read(buffer, offset, adjustedSize) một hoặc nhiều lần.

Dữ liệu được sao chép từ MQ của HAL vào bộ đệm máy khách.
Đã lọc mmtp với tiêu đề mmtp
được điền vào FMQ.
MMTP.RECORD không áp dụng Bắt buộc:
DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n]
RecordStatus::DATA_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

Không bắt buộc:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Đối với dữ liệu chỉ mục: for i=0; i<n; i++
DemuxFilterMmtpRecordEvent[i];


Đối với nội dung đã ghi , theo RecordStatus::* và lịch trình nội bộ, hãy thực hiện một trong các thao tác sau:
  • Chạy DvrRecord.write(adjustedSize) một hoặc nhiều lần để lưu trữ.
    Dữ liệu được chuyển từ MQ của HAL sang bộ lưu trữ.
  • Chạy DvrRecord.write(buffer, adjustedSize) một hoặc nhiều lần để đệm.
    Dữ liệu được sao chép từ MQ của HAL sang bộ đệm máy khách.
Đối với dữ liệu chỉ mục: Được mang trong tải trọng sự kiện.

Đối với nội dung được ghi: Luồng ghi được trộn lẫn chứa FMQ.

Nếu nguồn bộ lọc để ghi là TLV.TLV sang IP.IP có truyền qua thì luồng được ghi có tiêu đề TLV và IP.
MMTP.DOWNLOAD không áp dụng Bắt buộc:
DemuxFilterEvent::DemuxFilterDownloadEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Không bắt buộc:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterDownloadEvent[i].size)

Dữ liệu được sao chép từ MQ của HAL vào bộ đệm máy khách.
Gói tải xuống được điền vào FMQ bằng gói tải xuống IP khác.
IP.IP_PAYLOAD không áp dụng Bắt buộc:
DemuxFilterEvent::DemuxFilterIpPayloadEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Không bắt buộc:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterIpPayloadEvent[i].size)

Dữ liệu được sao chép từ MQ của HAL vào bộ đệm máy khách.
Gói tải trọng IP được điền vào FMQ bằng gói tải trọng IP khác.
IP.IP
TLV.TLV
ALP.ALP
isPassthrough:
true
Không bắt buộc:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Luồng phụ giao thức được lọc ra sẽ cung cấp bộ lọc tiếp theo trong chuỗi bộ lọc. không áp dụng
isPassthrough:
false
Bắt buộc:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Khuyến khích:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Theo sự kiện và lịch trình nội bộ, chạy
Filter.read(buffer, offset, adjustedSize) một hoặc nhiều lần.

Dữ liệu được sao chép từ MQ của HAL vào bộ đệm máy khách.
Luồng phụ giao thức được lọc ra với tiêu đề giao thức được điền vào FMQ.
IP.PAYLOAD_THROUGH
TLV.PAYLOAD_THROUGH
ALP.PAYLOAD_THROUGH
không áp dụng Không bắt buộc:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Tải trọng giao thức được lọc ra sẽ cung cấp bộ lọc tiếp theo trong chuỗi bộ lọc. không áp dụng
Luồng ví dụ sử dụng bộ lọc để xây dựng PSI/SI

Luồng ví dụ về cách sử dụng bộ lọc để xây dựng PSI/SI.

Hình 10. Quy trình xây dựng PSI/SI

  1. Mở một bộ lọc.

    Filter filter = tuner.openFilter(
      Filter.TYPE_TS,
      Filter.SUBTYPE_SECTION,
      /* bufferSize */1000,
      executor,
      filterCallback
    );
    
  2. Cấu hình và khởi động bộ lọc.

    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. Phần xử lý 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); }
          }
        }
    };
    
Luồng mẫu để sử dụng MediaEvent từ bộ lọc

Luồng mẫu để sử dụng MediaEvent từ bộ lọc.

Hình 11. Luồng sử dụng MediaEvent từ bộ lọc

  1. Mở, định cấu hình và khởi động bộ lọc A/V.
  2. Xử lý MediaEvent .
  3. Nhận MediaEvent .
  4. Xếp hàng khối tuyến tính vào codec .
  5. Nhả tay cầm A/V khi dữ liệu đã được sử dụng.

Android.media.tv.tuner.dvr

DvrRecorder cung cấp các phương pháp ghi này.

  • configure
  • attachFilter
  • detachFilter
  • start
  • flush
  • stop
  • setFileDescriptor
  • write

DvrPlayback cung cấp các phương pháp này để phát lại.

  • configure
  • start
  • flush
  • stop
  • setFileDescriptor
  • read

DvrSettings được sử dụng để cấu hình DvrRecorderDvrPlayback . OnPlaybackStatusChangedListenerOnRecordStatusChangedListener được sử dụng để báo cáo trạng thái của phiên bản DVR.

Luồng ví dụ để bắt đầu một bản ghi

Luồng ví dụ để bắt đầu một bản ghi.

Hình 12. Quy trình bắt đầu một bản ghi

  1. Mở, định cấu hình và khởi động 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. Nhận RecordEvent và lấy thông tin chỉ mục.

    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. Khởi tạo OnRecordStatusChangedListener và lưu trữ dữ liệu bản ghi.

      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);
          }
        }
      };
    

Bộ chỉnh HAL

Tuner HAL tuân theo HIDL và xác định giao diện giữa khung và phần cứng của nhà cung cấp. Các nhà cung cấp sử dụng giao diện để triển khai Tuner HAL và khung sử dụng nó để giao tiếp với việc triển khai Tuner HAL.

Mô-đun

Bộ chỉnh HAL 1.0

Mô-đun Điều khiển cơ bản Điều khiển dành riêng cho mô-đun Tệp HAL
ITuner không áp dụng 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

Bộ điều chỉnh HAL 1.1 (bắt nguồn từ Bộ điều chỉnh HAL 1.0)

Mô-đun Điều khiển cơ bản Điều khiển dành riêng cho mô-đun Tệp HAL
ITuner không áp dụng 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

Sơ đồ luồng tương tác giữa các mô-đun của Tuner HAL.

Hình 13. Sơ đồ tương tác giữa các mô-đun Tuner HAL

Liên kết bộ lọc

Tuner HAL hỗ trợ liên kết bộ lọc sao cho các bộ lọc có thể được liên kết với các bộ lọc khác cho nhiều lớp. Các bộ lọc tuân theo các quy tắc dưới đây.

  • Các bộ lọc được liên kết dưới dạng cây, không được phép đóng đường dẫn.
  • Nút gốc là demux.
  • Bộ lọc hoạt động độc lập.
  • Tất cả các bộ lọc bắt đầu nhận dữ liệu.
  • Liên kết bộ lọc xả vào bộ lọc cuối cùng.

Khối mã bên dưới và Hình 14 minh họa một ví dụ về lọc nhiều lớp.

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>)
}

Sơ đồ ví dụ liên kết bộ lọc.

Hình 14. Sơ đồ luồng liên kết bộ lọc cho nhiều lớp

Trình quản lý tài nguyên bộ điều chỉnh

Trước Trình quản lý tài nguyên Tuner (TRM), việc chuyển đổi giữa hai ứng dụng yêu cầu cùng một phần cứng Tuner. Khung đầu vào TV (TIF) đã sử dụng cơ chế "người đầu tiên giành được chiến thắng", nghĩa là ứng dụng nào nhận được tài nguyên trước sẽ giữ tài nguyên đó. Tuy nhiên, cơ chế này có thể không lý tưởng đối với một số trường hợp sử dụng phức tạp.

TRM hoạt động như một dịch vụ hệ thống để quản lý tài nguyên phần cứng Tuner, TVInput và CAS cho ứng dụng. TRM sử dụng cơ chế "chiến thắng ở nền trước", tính toán mức độ ưu tiên của ứng dụng dựa trên trạng thái nền trước hoặc nền sau của ứng dụng và loại trường hợp sử dụng. TRM cấp hoặc thu hồi tài nguyên dựa trên mức độ ưu tiên. TRM tập trung quản lý tài nguyên ATV cho phát sóng, OTT và DVR.

Giao diện TRM

TRM hiển thị các giao diện AIDL trong ITunerResourceManager.aidl cho khung Tuner, MediaCasTvInputHardwareManager để đăng ký, yêu cầu hoặc giải phóng tài nguyên.

Các giao diện quản lý khách hàng được liệt kê dưới đây.

  • registerClientProfile(in ResourceClientProfile profile, IResourcesReclaimListener listener, out int[] clientId)
  • unregisterClientProfile(in int clientId)

Các giao diện để yêu cầu và giải phóng tài nguyên được liệt kê dưới đây.

  • 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

Các lớp khách hàng và yêu cầu được liệt kê dưới đây.

  • ResourceClientProfile
  • ResourcesReclaimListener
  • TunerFrontendRequest
  • TunerDemuxRequest
  • TunerDescramblerRequest
  • CasSessionRequest
  • TunerLnbRequest

Ưu tiên khách hàng

TRM tính toán mức độ ưu tiên của máy khách bằng cách sử dụng các tham số từ hồ sơ của máy khách và giá trị mức độ ưu tiên từ tệp cấu hình. Mức độ ưu tiên cũng có thể được cập nhật theo giá trị ưu tiên tùy ý từ máy khách.

Các thông số trong hồ sơ của khách hàng

TRM truy xuất ID tiến trình từ mTvInputSessionId để quyết định xem ứng dụng là ứng dụng nền trước hay ứng dụng nền. Để tạo mTvInputSessionId , TvInputService.onCreateSession hoặc TvInputService.onCreateRecordingSession khởi tạo phiên TIS.

mUseCase cho biết trường hợp sử dụng của phiên. Các trường hợp sử dụng được xác định trước được liệt kê dưới đây.

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
}

Tập tin cấu hình

Tệp cấu hình mặc định

Tệp cấu hình mặc định bên dưới cung cấp các giá trị ưu tiên cho các trường hợp sử dụng được xác định trước. Người dùng có thể thay đổi các giá trị bằng cách sử dụng tệp cấu hình tùy chỉnh .

Trường hợp sử dụng Vấn đề xung quanh Lý lịch
LIVE 490 400
PLAYBACK 480 300
RECORD 600 500
SCAN 450 200
BACKGROUND 180 100
Tập tin cấu hình tùy chỉnh

Nhà cung cấp có thể tùy chỉnh tệp cấu hình /vendor/etc/tunerResourceManagerUseCaseConfig.xml . Tệp này được sử dụng để thêm, xóa hoặc cập nhật các loại ca sử dụng và các giá trị ưu tiên của ca sử dụng. Tệp tùy chỉnh có thể sử dụng platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml làm mẫu.

Ví dụ: trường hợp sử dụng của nhà cung cấp mới là VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000] . Định dạng phải tuân theo platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd .

Giá trị ưu tiên tùy ý và giá trị đẹp

TRM cung cấp updateClientPriority để khách hàng cập nhật giá trị ưu tiên tùy ý và giá trị Nice. Giá trị ưu tiên tùy ý ghi đè giá trị ưu tiên được tính từ loại trường hợp sử dụng và ID phiên.

Giá trị Nice biểu thị mức độ khoan dung của hành vi của khách hàng khi nó xung đột với khách hàng khác. Giá trị tốt làm giảm giá trị ưu tiên của khách hàng trước khi giá trị ưu tiên của nó được so sánh với khách hàng thách thức.

Cơ chế thu hồi

Sơ đồ bên dưới cho thấy cách thu hồi và phân bổ tài nguyên khi xảy ra xung đột tài nguyên.

Sơ đồ quy trình cơ chế thu hồi.

Hình 15. Sơ đồ cơ chế thu hồi xung đột giữa các tài nguyên Tuner