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 quy trình phần cứng của các nhà cung cấp, giúp phù hợp với cả SoC cấp thấp và cấp cao. 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ằng môi trường thực thi đáng tin cậy (TEE) và đường dẫn nội dung đa phương tiện bảo mật (SMP), cho phép sử dụng khung này trong môi trường bảo vệ nội dung bị hạn chế nghiêm ngặt.

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

Thành phần

Đối với Android 11, có 3 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 SDK của bộ chỉnh âm: Giao diện giữa khung và ứng dụng
  • Trình quản lý tài nguyên của bộ thu (TRM): Điều phối tài nguyên phần cứng của bộ thu

Đối với Android 11, các thành phần sau đây đã đượ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 bộ mã hoá và giải mã nội dung nghe nhìn
  • AudioTrack hoặc bản âm thanh
  • MediaResourceManager hoặc trình quản lý tài nguyên đa phương tiện (MRM)

Sơ đồ quy trình của các thành phần trong khung Tuner.

Hình 1. Hoạt động tương tác giữa các thành phần của Android TV

Tính năng

Giao diện người dùng hỗ trợ các tiêu chuẩn DTV dưới đây.

  • ATSC
  • ATSC3
  • DVB C/S/T
  • ISDB S/S3/T
  • Đồng hồ kim

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

  • DTMB

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

  • Luồng truyền tải (TS)
  • Giao thức truyền tải nội dung đa 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)

Trình giải mã hỗ trợ các biện pháp bảo vệ nội dung dưới đây.

  • Đường dẫn nội dung nghe nhìn an toàn
  • Xoá đường dẫn nội dung nghe nhìn
  • Bảo mật bản ghi cục bộ
  • Phát trên thiết bị một cách an toàn

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

  • Quét
  • Sự kiện phát trực tiếp
  • Phát
  • Ghi âm

Bộ điều chỉnh, 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ó tay điều khiển bộ nhớ an toàn
  • Chế độ thực tế

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ì mà khung này mong đợi từ nhà cung cấp và cách nhà cung cấp có thể thực hiện.
  • Xuất các chức năng của giao diện người dùng, bộ giải mã và bộ giải mã sang khung thông qua giao diện IFrontend, IDemux, IDescrambler, IFilter, IDvrILnb.
  • Bao gồm các hàm để tích hợp Tuner HAL với các thành phần khung khác, chẳng hạn như MediaCodecAudioTrack.

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

  • Tuner Java API cho phép ứng dụng truy cập vào 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 bằng Tuner HAL.
  • Mô-đun Bộ chỉnh âm gốc là cầu nối giữa lớp Java của Bộ chỉnh âm và HAL của Bộ chỉnh âm.

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

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

Media CAS và CAS HAL được nâng cao bằng các tính năng dưới đây.

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

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

  • Lấy bộ nhớ A/V bảo mật làm dữ liệu đầu vào nội dung.
  • Được định cấu hình để đồng bộ hoá A/V phần cứng trong chế độ phát qua đường hầm.
  • Định cấu hình tính năng hỗ trợ cho ES_payload và chế độ truyền thẳng.

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ể

Sơ đồ dưới đây minh hoạ trình tự lệnh gọi để phát sự kiện phát trực tiếp.

Thiết lập

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

Hình 3. Trình tự thiết lập để phát sự kiện phát trực tiếp

Xử lý A/V

Sơ đồ xử lý A/V cho bản phát sóng trực tiếp.

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

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

Sơ đồ xử lý nội dung bị xáo trộn cho bản phát sóng trực tiếp.

Hình 5. Xử lý nội dung bị xáo trộn để phát 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 biểu đồ phát sóng trực tiếp.

Hình 6. Xử lý A/V để phát sự kiện phát trực tiếp

API Tuner SDK

API Tuner SDK xử lý các hoạt động 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 vào các tài nguyên và thành phần phụ của Tuner, chẳng hạn như bộ lọc và bộ giải mã. Giao diện người dùng và trình phân tách là các thành phần nội bộ.

Sơ đồ quy trình của API SDK Trình điều chỉnh.

Hình 7. Tương tác với API SDK của Trình điều chỉnh

Phiên bản

Kể từ Android 12, API SDK của Tuner hỗ trợ tính năng mới trong Tuner HAL 1.1, đây là bản nâng cấp phiên bản 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 tối thiểu bắt buộc trong tài liệu về các API Android 12 mới.

Gói

API SDK của Trình điều chỉnh cung cấp 4 gói dưới đây.

  • 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 SDK Trình điều chỉnh.

Hình 8. Gói API SDK của Trình điều chỉnh

Android.media.tv.tuner

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

  • tuner(): Khởi chạy một thực thể Tuner bằng cách chỉ định các tham số useCasesessionId.
  • tune(): Thu nạ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(): Thu nạp một thực thể bộ lọc bằng cách chỉ định loại bộ lọc.
  • openDvrRecorder(): Thu thập một thực thể bản ghi bằng cách chỉ định kích thước vùng đệm.
  • openDvrPlayback(): Thu nạp một thực thể phát bằng cách chỉ định kích thước vùng đệm.
  • openDescrambler(): Thu nạp một thực thể giải mã.
  • openLnb(): Thu nạp một thực thể LNB nội bộ.
  • openLnbByName(): Thu nạp một thực thể LNB bên ngoài.
  • openTimeFilter(): Thu nạp một thực thể bộ lọc thời gian.

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

  • 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 tập hợp chế độ cài đặt, thông tin, trạng thái, sự kiện và chức năng liên quan đến giao diện người dùng.

Lớp

FrontendSettings được lấy từ các lớp dưới đây cho nhiều tiêu chuẩn DTV.

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

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

  • DtmbFrontendSettings

FrontendCapabilities được lấy từ các lớp dưới đây cho nhiều tiêu chuẩn DTV.

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

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

  • DtmbFrontendCapabilities

FrontendInfo truy xuất 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 theo dõi các sự kiện trên giao diện người dùng. Ứng dụng TIS sử dụng ScanCallback để xử lý thông báo 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à tạo một 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ụ: mã PLD), thì bạn nên chọn Tuner.tune làm phương án nhanh hơn.

Khi người dùng gọi Tuner.tune, các thao tác sau sẽ xảy ra:

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

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

Trong quá trình điều chỉnh, bạn có thể gọi stopTune() hoặc close() để tạm dừng hoặc kết thúc lệnh 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 chuẩn (ví dụ: DVB T/C/S), thì bạn nên sử dụng Tuner.scan(AUTO_SCAN).

Khi người dùng gọi Tuner.scan(AUTO_SCAN), các thao tác sau sẽ xảy ra:

  • TIS sử dụng Tuner.scan(AUTO_SCAN) với FrontendSettings được điền sẵn tần suất.

  • HAL báo cáo quét các thông báo LOCKED nếu tín hiệu bị khoá. 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 chuyển sang chế độ cài đặt tiếp theo ở cùng tần số. Nếu cấu trúc FrontendSettings trống, HAL sẽ sử dụng chế độ cài đặt có sẵn tiếp theo. Nếu không, HAL sẽ sử dụng FrontendSettings để quét một lần và gửi END để cho biết rằng thao tác quét đã hoàn tất.

  • TIS lặp lại các thao tác ở trên cho đến khi hết tất cả các chế độ cài đặt về tần suất.

  • HAL gửi END để cho biết rằng thao tác quét đã hoàn tất.

  • TIS sẽ chuyển sang tần số có sẵn tiếp theo trong danh sách tần số.

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

Trong khi 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 suất và HAL của nhà cung cấp có thể tìm kiếm tần suất 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ì bạn nên sử dụng Tuner.scan(BLIND_SCAN).

  • TIS sử dụng Tuner.scan(BLIND_SCAN). Bạn có thể chỉ định tần suất trong FrontendSettings cho tần suất bắt đầu, nhưng TIS sẽ bỏ qua các chế độ cài đặt khác trong FrontendSettings.
  • HAL báo cáo thông báo quét LOCKED nếu tín hiệu bị khoá.
  • 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 sẽ bị bỏ qua.)
  • TIS lặp lại các thao tác ở trên cho đến khi hết tất cả các chế độ cài đặt về tần suất. HAL tăng tần suất mà TIS không cần làm gì cả. HAL báo cáo PROGRESS.

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

Trong khi 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 quét TIS.

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

Android.media.tv.tuner.filter

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

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

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

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

  • AlpFilterConfiguration
  • IpFilterConfiguration
  • MmtpFilterConfiguration
  • TlvFilterConfiguration
  • TsFilterConfiguration

Các chế độ cài đặt này được lấy từ các lớp bên dưới. Các chế độ cài đặt này dành cho loại bộ lọc phụ và chỉ định những 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 sự kiện cho nhiều loại dữ liệu.

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

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

  • IpCidChangeEvent
  • RestartEvent
  • ScramblingStatusEvent
Sự kiện và định dạng dữ liệu từ bộ lọc
Loại bộ 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

Nên:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Theo sự kiện và lịch biểu nội bộ, hãy 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 vùng đệm của ứng dụng.
Một gói phiên đã tập hợ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 vùng đệm của ứng dụng.
TS.PES isRaw:
true
Bắt buộc:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Nên:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Theo sự kiện và lịch biểu nội bộ, hãy 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 vùng đệm của ứng dụng.
Một gói PES đã lắp ráp đượ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 vùng đệm của ứng dụng.
MMTP.PES isRaw:
true
Bắt buộc:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Nên:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Theo sự kiện và lịch biểu nội bộ, hãy 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 vùng đệm của ứng dụng.
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 vùng đệm của ứng dụng.
TS.TS
Không áp dụng Bắt buộc:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Nên:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Theo sự kiện và lịch biểu nội bộ, hãy 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 vùng đệm của ứng dụng.
Lọc ra ts có 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
Ứng dụng có thể bắt đầu MediaCodec sau khi nhận được DemuxFilterStatus::DATA_READY.
Ứng dụng 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
Cách sử dụng MediaCodec:
for i=0; i<n; i++
linearblock = MediaEvent[i].getLinearBlock();
codec.startQueueLinearBlock(linearblock)
linearblock.recycle()


Cách sử dụng tính nă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 một phần dữ liệu ES trong bộ nhớ ION.
TS.PCR
IP.NTP
ALP.PTP
Không áp dụng Bắt buộc: Không áp dụng
Không bắt buộc: Không áp dụng
Không áp dụng Không có câu trả lời thích hợp
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 được ghi lại, theo RecordStatus::* và lịch biểu nội bộ, hãy làm một trong những việc sau:
  • Chạy DvrRecord.write(adustedSize) một hoặc nhiều lần để lưu trữ.
    Dữ liệu được chuyển từ MQ của HAL sang bộ nhớ.
  • Chạy DvrRecord.write(buffer, adustedSize) một hoặc nhiều lần để lưu vào bộ đệm.
    Dữ liệu được sao chép từ MQ của HAL vào vùng đệm của ứng dụng.
Đối với dữ liệu chỉ mục: Được đưa vào tải trọng sự kiện.

Đối với nội dung được ghi lại: Luồng TS được kết hợp đượ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

Nên:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Theo sự kiện và lịch biểu nội bộ, hãy 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 vùng đệm của ứng dụng.
Lọc ra mmtp có 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 được ghi lại, theo RecordStatus::* và lịch biểu nội bộ, hãy làm theo một trong những cách sau:
  • Chạy DvrRecord.write(adjustedSize) 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ộ nhớ.
  • Chạy DvrRecord.write(buffer, adjustedSize) một hoặc nhiều lần để lưu vào bộ đệm.
    Dữ liệu được sao chép từ MQ của HAL vào vùng đệm của ứng dụng.
Đối với dữ liệu chỉ mục: Được đưa vào tải trọng sự kiện.

Đối với nội dung đã ghi: Luồng ghi được đã kết hợp được điền vào FMQ.

Nếu nguồn bộ lọc để ghi là TLV.TLV đến IP.IP với tính năng truyền qua, thì luồng đã ghi sẽ 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 vùng đệm của ứng dụng.
Gói tải xuống được điền vào FMQ bằng một 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 vùng đệm của ứng dụng.
Gói trọng tải IP được điền vào FMQ bằng một gói trọng tải 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 đã lọc sẽ cung cấp cho 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

Nên:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Theo sự kiện và lịch biểu nội bộ, hãy 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 vùng đệm của ứng dụng.
Luồng phụ giao thức đã lọc 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
Trọng tải giao thức đã lọc sẽ cung cấp cho bộ lọc tiếp theo trong chuỗi bộ lọc. Không áp dụng
Ví dụ về quy trình sử dụng bộ lọc để tạo PSI/SI

Quy trình mẫu để sử dụng bộ lọc nhằm tạo PSI/SI.

Hình 10. Quy trình tạo PSI/SI

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

    Filter filter = tuner.openFilter(
      Filter.TYPE_TS,
      Filter.SUBTYPE_SECTION,
      /* bufferSize */1000,
      executor,
      filterCallback
    );
    
  2. Định cấu hình và bắt đầu 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. 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 ví dụ để sử dụng MediaEvent từ bộ lọc

Luồng ví dụ để 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. Đặt khối tuyến tính vào hàng đợi codec.
  5. Giải phóng tay điều khiển A/V khi dữ liệu đã được sử dụng.

Android.media.tv.tuner.dvr

DvrRecorder cung cấp các phương thức này để ghi lại.

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

DvrPlayback cung cấp các phương thức này để phát.

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

DvrSettings dùng để định cấu hình DvrRecorderDvrPlayback. OnPlaybackStatusChangedListenerOnRecordStatusChangedListener được dùng để báo cáo trạng thái của một thực thể DVR.

Quy trình mẫu để bắt đầu ghi

Quy trình mẫu để bắt đầu ghi.

Hình 12. Quy trình bắt đầu 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à truy xuất 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 chạy 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);
          }
        }
      };
    

HAL bộ dò

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. Nhà cung cấp sử dụng giao diện này để triển khai Tuner HAL và khung sử dụng giao diện này để giao tiếp với quá trình triển khai Tuner HAL.

Mô-đun

Tuner HAL 1.0

Mô-đun Các thao tác điều khiển cơ bản Các chế độ đ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

Tuner HAL 1.1 (phát sinh từ Tuner HAL 1.0)

Mô-đun Các thao tác điều khiển cơ bản Các chế độ đ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ơ đồ quy trình tương tác giữa các mô-đun của Tuner HAL.

Hình 13. Sơ đồ về các hoạt động 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 để 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.

  • 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.
  • Các bộ lọc hoạt động độc lập.
  • Tất cả bộ lọc bắt đầu nhận dữ liệu.
  • Đường liên kết bộ lọc sẽ xả trên bộ lọc cuối cùng.

Khối mã bên dưới và Hình 14 minh hoạ ví dụ về cách 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ụ về mối liên kết bộ lọc.

Hình 14. Sơ đồ quy trình của mối liên kết bộ lọc cho nhiều lớp

Trình quản lý tài nguyên bộ dò

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

TRM chạy dưới dạng dịch vụ hệ thống để quản lý tài nguyên phần cứng Tuner, TVInput và CAS cho các ứng dụng. TRM sử dụng cơ chế "foreground win" (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 truyền hình, OTT và DVR.

Giao diện TRM

TRM hiển thị các giao diện AIDL trong ITunerResourceManager.aidl cho khung Trình điều chỉnh, MediaCasTvInputHardwareManager để đăng ký, yêu cầu hoặc phát hành tài nguyên.

Dưới đây là danh sách các giao diện để quản lý ứng dụng khách.

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

Dưới đây là danh sách các giao diện để yêu cầu và giải phóng tài nguyên.

  • 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

Dưới đây là danh sách các lớp ứng dụng và yêu cầu.

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

Mức độ ưu tiên của ứng dụng

TRM tính toán mức độ ưu tiên của ứng dụng bằng cách sử dụng các tham số từ hồ sơ của ứng dụng 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 bằng một giá trị ưu tiên tuỳ ý từ ứng dụng.

Tham số trong hồ sơ của ứng dụng

TRM truy xuất mã nhận dạng quy trình từ mTvInputSessionId để quyết định xem một ứng dụng là ứng dụng trên nền trước hay nền sau. Để tạo mTvInputSessionId, TvInputService.onCreateSession hoặc TvInputService.onCreateRecordingSession, hãy khởi chạy một 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ê bên dưới.

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 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ị mức độ ư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 tuỳ chỉnh.

Trường hợp sử dụng Nền trước Thông tin khái quát
LIVE 490 400
PLAYBACK 480 300
RECORD 600 500
SCAN 450 200
BACKGROUND 180 100
Tệp cấu hình tuỳ chỉnh

Nhà cung cấp có thể tuỳ chỉnh tệp cấu hình /vendor/etc/tunerResourceManagerUseCaseConfig.xml. Tệp này được dùng để thêm, xoá hoặc cập nhật các loại trường hợp sử dụng và giá trị mức độ ưu tiên của trường hợp sử dụng. Tệp tuỳ 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 mới của nhà cung cấp 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 tuỳ ý và giá trị tốt

TRM cung cấp updateClientPriority để ứng dụng cập nhật giá trị ưu tiên và giá trị tốt tuỳ ý. Giá trị mức độ ưu tiên tuỳ ý sẽ ghi đè giá trị mức độ ưu tiên được tính toán từ loại trường hợp sử dụng và mã phiên.

Giá trị nice cho biết hành vi của ứng dụng khách có dễ chịu hay không khi xung đột với một ứng dụng khách khác. Giá trị tốt làm giảm giá trị ưu tiên của ứng dụng trước khi giá trị ưu tiên của ứng dụng được so sánh với ứng dụng khó khăn.

Cơ chế xác nhận lại

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

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

Hình 15. Sơ đồ về cơ chế thu hồi khi xảy ra xung đột giữa các tài nguyên của Trình điều chỉnh