Khung bộ dò

Đối với Android 11 trở lên, bạn có thể dùng ứng dụng Android Bộ điều chỉnh khung để phân phối nội dung nghe nhìn. Khung này sử dụng phần cứng từ các nhà cung cấp, nhờ đó giải pháp này phù hợp với cả SoC cấp thấp và cao cấp. Khung này mang lại một cách an toàn để phân phối nội dung nghe nhìn đượ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 nghe nhìn bảo mật (SMP), cho phép môi trường đó để sử dụng 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 Tuner và Android CAS mang lại trải nghiệm nhanh hơn tích hợp giữa nhà cung cấp Tuner và nhà cung cấp CAS. Giao diện Tuner hoạt động với MediaCodecAudioTrack nhằm xây dựng một giải pháp toàn cầu cho Android TV. Giao diện Tuner hỗ trợ cả TV kỹ thuật số lẫn TV analog dựa trên chuẩn truyền tin.

Thành phần

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

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

Đối với Android 11, các thành phần sau đã được nâng cao.

  • CAS phiên bản 2
  • TvInputService hoặc Dịch vụ đầu vào TV (TIS)
  • TvInputManagerService hoặc Dịch vụ trình quản lý đầu vào TV (TIMS)
  • MediaCodec hoặc bộ mã hoá và giải mã nội dung đa phương tiệ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 bộ dò.

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 có Tuner HAL 1.1 trở lên hỗ trợ tiêu chuẩn DTV dưới đây.

  • DTMB

Demux hỗ trợ các giao thức phát trực tuyến ở bên dưới.

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

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

  • Đường dẫn nội dung nghe nhìn bảo mật
  • 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 Trình theo dõi 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ộ dò, MediaCodecAudioTrack hỗ trợ các chế độ luồng dữ liệu dưới đây.

  • Tải trọng ES có vùng đệm bộ nhớ rõ ràng
  • Tải trọng ES có xử lý bộ nhớ an toàn
  • Môi trường thực tế ảo

Thiết kế tổng thể

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

  • Mô tả những gì khung này trông đợi từ nhà cung cấp và cách nhà cung cấp có thể làm việc đó.
  • Xuất các chức năng của giao diện người dùng, demux và giải mã sang khung thông qua IFrontend, IDemux, IDescrambler, IFilter, IDvr, và giao diện ILnb.
  • Bao gồm các chức năng để tích hợp HAL Tuner với khung khác như MediaCodecAudioTrack.

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

  • Tuner Java API cho phép các ứng dụng truy cập vào Tuner HAL (Lớp trừu tượng phần cứng) 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ý số lượng lớn ghi hoặc phát dữ liệu bằng HAL của bộ dò.
  • Mô-đun Bộ dò gốc là cầu nối giữa lớp Tuner Java và Tuner Lớp trừu tượng phần cứng (HAL).

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

  • Quản lý các tài nguyên trên Tuner ( Tuner), chẳng hạn như Frontend, LNB (Giao diện người dùng), Các phiên CAS và thiết bị đầu vào TV qua lớp HAL đầu vào TV.
  • Áp dụng các quy tắc để xác nhận lại đủ tài nguyên từ của chúng tôi. Quy tắc mặc định là chiến thắng ở chế độ nền trước.

CAS truyền thông và CAS HAL được cải tiến với các tính năng dưới đây.

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

MediaCodecAudioTrack được cải thiện bằng các tính năng dưới đây.

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

Thiết kế tổng thể của Bộ dò HAL.

Hình 2. Sơ đồ các thành phần trong HAL bộ dò

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

Các sơ đồ dưới đây minh hoạ trình tự cuộc gọi để phát nội dung phát sóng trực tiếp.

Thiết lập

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

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

Xử lý A/V

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

Hình 4. Xử lý A/V để phát 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 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 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 chương trình phát sóng trực tiếp.

Hình 6. Đang xử lý A/V để phát chương trình truyền hình trực tiếp

API bộ dò SDK

Tuner SDK API xử lý các tương tác với Tuner JNI, Tuner HAL (Lớp trừu tượng phần cứng), và TunerResourceManager. Ứng dụng TIS dùng Tuner SDK API để truy cập Tuner các tài nguyên và thành phần phụ như bộ lọc và bộ giải mã (descrambler). Giao diện người dùng và demux là các thành phần nội bộ.

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

Hình 7. Hoạt động tương tác với Tuner SDK API

Phiên bản

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

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

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

Bạn có thể xem phiên bản HAL (Lớp trừu tượng phần cứng) tối thiểu trong tài liệu về API Android 12 mới.

Gói

Tuner SDK API 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 Tuner SDK.

Hình 8. Gói API bộ theo dõi SDK

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 tạo 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 useCase và Tham số sessionId.
  • 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 nạp một thực thể bản ghi bằng cách chỉ định vùng đệm kích thước.
  • openDvrPlayback(): Thu nạp một thực thể phát bằng cách chỉ định vùng đệm kích thước.
  • openDescrambler(): Nhận một thực thể giải mã.
  • openLnb(): Nhận một thực thể LNB nội bộ.
  • openLnbByName(): Nhận một thực thể LNB bên ngoài.
  • openTimeFilter(): Nhận một 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 bộ lọc, DVR và các gói 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.cho các giao diện người dùng

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

Lớp

FrontendSettings được tạo ra cho các tiêu chuẩn DTV khác nhau theo các lớp dưới đây.

  • 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 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, 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 quét các tần số có thể có và tạo một kênh để người dùng tiếp cận. TIS có thể sử dụng Tuner.tune, Tuner.scan(BLIND_SCAN) hoặc Tuner.scan(AUTO_SCAN) để hoàn tất kênh quét.

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), sau đó Tuner.tune được đề xuất làm lựa chọn nhanh hơn.

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

  • TIS điền thông tin bắt buộc vào FrontendSettings bằng Tuner.tune.
  • Báo cáo HAL sẽ điều chỉnh thông báo 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 chuyển đến tần suất có sẵn tiếp theo trong danh sách tần suất.

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

Trong khi nghe, 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.

Bộ dò.scan(auto_SCAN)

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

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

  • TIS sử dụng Tuner.scan(AUTO_SCAN)FrontendSettings được lấp đầy tần suất.

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

  • TIS lặp lại các thao tác nêu trên cho đến khi tất cả các chế độ cài đặt về tần suất đều được kiệt sức.

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

  • TIS chuyển đến tần suất có sẵn tiếp theo trong danh sách tần suất.

TIS gọi lại Tuner.scan(AUTO_SCAN) cho đến khi hết tất cả 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é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 nhận tài nguyên giao diện người dùng do người dùng chỉ định, sau đó Tuner.scan(BLIND_SCAN) là thời điểm được đề xuất.

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

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ơ đồ luồng của 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 hoạt động lọc cùng với cấu hình, các chế độ cài đặt, lệnh gọi lại và sự kiện. Gói 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 là cho loại bộ lọc chính và chúng chỉ định giao thức mà bộ lọc sử dụng trích xuất dữ liệu.

  • AlpFilterConfiguration
  • IpFilterConfiguration
  • MmtpFilterConfiguration
  • TlvFilterConfiguration
  • TsFilterConfiguration

Chế độ cài đặt bắt nguồn từ các lớp bên dưới. Chế độ cài đặt này là dành cho bộ lọc loại phụ và xác đị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 dưới đây để báo cáo sự kiện cho các kiểu các loại dữ liệu khác nhau.

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

Từ Android 12 có Bộ dò HAL 1.1 trở lên, bạn có thể dùng các sự kiện sau đây.

  • 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 đối với 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 dùng:

DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER
Tuỳ theo sự kiện và lịch biểu nội bộ, hãy chạy
Filter.read(buffer, offset, adjustedSize) một trở lên lần.

Dữ liệu được sao chép từ MQ của HAL vào vùng đệm ứng dụng.
Một gói phiên được tập hợp được điền vào FMQ bởi một gói 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 ứng dụng.
TS.PES isRaw:
true
Bắt buộc:

DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Nên dùng:

DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER
Tuỳ theo sự kiện và lịch biểu nội bộ, hãy chạy
Filter.read(buffer, offset, adjustedSize) một trở lên lần.

Dữ liệu được sao chép từ MQ của HAL vào vùng đệm ứng dụng.
Một gói PES đã tập hợp được điền FMQ bằng một gói khác Gói PES.
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 ứng dụng.
MMTP.PES isRaw:
true
Bắt buộc:

DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Nên dùng:

DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER
Tuỳ theo sự kiện và lịch biểu nội bộ, hãy chạy
Filter.read(buffer, offset, adjustedSize) một trở lên lần.

Dữ liệu được sao chép từ MQ của HAL vào vùng đệm ứng dụng.
Một gói MFU được lắp ráp được điền FMQ bởi một gói khác Gói MFU.
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 ứng dụng.
TS.TS
Không áp dụng Bắt buộc:

DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Nên dùng:

DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER
Tuỳ theo sự kiện và lịch biểu nội bộ, hãy chạy
Filter.read(buffer, offset, adjustedSize) một trở lên lần.

Dữ liệu được sao chép từ MQ của HAL vào vùng đệm ứng dụng.
Đã lọc ra ts có tiêu đề ts
được điền trong 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 dùng MediaCodec:

for i=0; i<n; i++
linearblock = MediaEvent[i].getLinearBlock();
codec.startQueueLinearBlock(linearblock)
linearblock.recycle()

Cách 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))
Dữ liệu 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

ngày DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER
Đối với dữ liệu lập chỉ mục:

for i=0; i<n; i++
DemuxFilterTsRecordEvent[i];

Đối với nội dung đã ghi lại, theo RecordStatus::* và lịch biểu nội bộ, một trong các lệnh 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ừ bộ nhớ MQ của HAL sang bộ nhớ.
  • Chạy DvrRecord.write(buffer, adustedSize) một hoặc nhiều lần vào bộ đệm.
    Dữ liệu được sao chép từ MQ của HAL vào vùng đệm ứ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 TS đã chuyển đổi được điền trong 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 dùng:

DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER
Tuỳ theo sự kiện và lịch biểu nội bộ, hãy chạy
Filter.read(buffer, offset, adjustedSize) một trở lên lần.

Dữ liệu được sao chép từ MQ của HAL vào vùng đệm ứng dụng.
Đã lọc ra mmtp có tiêu đề mmtp
được điền trong 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

ngày DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER
Đối với dữ liệu lập chỉ mục: for i=0; i<n; i++
DemuxFilterMmtpRecordEvent[i];


Đối với nội dung đã ghi lại, theo RecordStatus::* và lịch biểu nội bộ, hãy thực hiện một trong đang theo dõi:
  • Chạy DvrRecord.write(adjustedSize) một hoặc nhiều lần vào bộ nhớ.
    Dữ liệu được chuyển từ bộ nhớ MQ của HAL sang bộ nhớ.
  • Chạy DvrRecord.write(buffer, adjustedSize) một hoặc thời gian để lưu vào bộ đệm.
    Dữ liệu được sao chép từ MQ của HAL vào vùng đệm ứ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: Đã điền luồng nội dung đã ghi lại với nhau FMQ.

Nếu nguồn bộ lọc cho bản ghi là TLV.TLV đến IP.IP có truyền qua, sự kiện phát trực tiếp được ghi lại có Tiêu đề IP và TLV.
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 ứng dụng.
Gói tải xuống được điền FMQ bằng một gói tải 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 ứng dụng.
Gói tải trọng IP được điền FMQ bằng một 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
Đã lọc ra luồng phụ của giao thức cho bộ lọc tiếp theo trong bộ lọc của bạn. Không áp dụng
isPassthrough:
false
Bắt buộc:

DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Nên dùng:

DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER
Tuỳ theo sự kiện và lịch biểu nội bộ, hãy chạy
Filter.read(buffer, offset, adjustedSize) một trở lên lần.

Dữ liệu được sao chép từ MQ của HAL vào vùng đệm ứng dụng.
Đã lọc ra luồng phụ giao thức có 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
Đã lọc ra phần tải trọng giao thức cho bộ lọc tiếp theo trong bộ lọc của bạn. Không áp dụng
Quy trình ví dụ về cách sử dụng bộ lọc để xây dựng PSI/SI

Quy trình 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. Định cấu hình và bắt đầu 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); }
          }
        }
    };
    
Quy trình ví dụ để sử dụng MediaEvent từ bộ lọc

Quy trình ví dụ để sử dụng MediaEvent từ bộ lọc.

Hình 11. Quy trình để 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. Thêm khối tuyến tính vào hàng đợi theo codec.
  5. Thả 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 thức này để ghi.

  • 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 lại

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

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 động 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ộ dò HAL

Bộ dò 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 để triển khai HAL Tuner và khung sử dụng nó để giao tiếp với triển khai HAL của bộ dò.

Mô-đun

Bộ dò HAL 1.0

Mô-đun Các thao tác điều khiển cơ bản Chế độ điều khiển dành riêng cho từng 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 setLnb, stopScan 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ộ dò HAL 1.1 (lấy từ Bộ dò HAL 1.0)

Mô-đun Các thao tác điều khiển cơ bản Chế độ điều khiển dành riêng cho từng 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 Bộ dò HAL.

Hình 13. Sơ đồ tương tác giữa các mô-đun HAL của bộ dò

Lọc mối liên kết

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

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

Khối mã dưới đây và Hình 14 minh hoạ một ví dụ về cách lọc nhiều các 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ơ đồ luồng 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 Trình quản lý tài nguyên bộ dò (TRM), việc chuyển đổi giữa hai ứng dụng bắt buộc phải có cùng một phần cứng bộ dò. Khung đầu vào TV (TIF) sử dụng chiến lược " giành chiến thắng đầu tiên" cơ chế đó, tức là bất kỳ ứng dụng nào nhận tài nguyên trước sẽ giữ nguyên tài nguyên. Tuy nhiên, cơ chế này có thể không lý tưởng cho 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ý Bộ dò, TVInput và phần cứng CAS cho ứng dụng. TRM sử dụng "chiến thắng trên nền trước" cơ chế đó tính toán mức độ ưu tiên của ứng dụng dựa trên nền trước hoặc nền sau của ứng dụng trạng thái 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 việc quản lý tài nguyên ATV cho hoạt động phát sóng, OTT (trực tiếp qua Internet), và DVR.

Giao diện TRM

TRM tiết lộ giao diện AIDL trong ITunerResourceManager.aidl cho Tuner khung, MediaCasTvInputHardwareManager để đăng ký, yêu cầu hoặc phát hành tài nguyên.

Các giao diện để quản lý ứng dụng được liệt kê bên dưới.

  • 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à huỷ bỏ 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

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

  • 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ừ cấu hình và giá trị ưu tiên từ tệp cấu hình. Mức độ ưu tiên có thể cũng được cập nhật theo một giá trị ưu tiên tuỳ ý từ ứng dụng.

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

TRM truy xuất mã nhận dạng tiến trình từ mTvInputSessionId để quyết định xem một ứng dụng là ứng dụng chạy trên nền trước hoặc nền sau. Cách tạo mTvInputSessionId: TvInputService.onCreateSession hoặc TvInputService.onCreateRecordingSession sẽ 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 là đượ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ị ưu tiên cho mục đích sử dụng định sẵn trường hợp. 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 được 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 sử dụng để thêm, xoá hoặc cập nhật loại trường hợp sử dụng và giá trị ư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ụ: một 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 thủ 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 tuỳ ý giá trị ưu tiên và giá trị tốt. Giá trị mức độ ưu tiên tuỳ ý sẽ ghi đè giá trị ưu tiên đã tính từ loại trường hợp sử dụng và mã phiên.

Giá trị tốt cho biết mức độ nhẹ nhàng của hành vi của ứng dụng khi ở trong xung đột với ứng dụng khách khác. Giá trị tốt sẽ giảm mức độ ưu tiên của khách hàng trước khi so sánh với khách hàng có thách thức.

Cơ chế xác nhận lại quyền sở hữu

Sơ đồ dưới đây cho biết cách lấy lại và chỉ định tài nguyên khi xung đột tài nguyên sẽ xảy ra.

Sơ đồ quy trình cơ chế xác nhận lại quyền sở hữu.

Hình 15. Sơ đồ về cơ chế xác nhận lại quyền sở hữu khi có xung đột giữa Bộ dò tài nguyên