Đố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 nhà cung cấ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 thức bảo mật để 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 bảo mật cho nội dung nghe nhìn (SMP), cho phép sử dụng trong một môi trường bảo vệ nội dung có tính hạn chế cao.
Giao diện được chuẩn hoá giữa Tuner và Android CAS giúp việc tích hợp giữa nhà cung cấp Tuner và nhà cung cấp CAS diễn ra nhanh hơn. Giao diện Tuner hoạt động với MediaCodec
và AudioTrack
để tạo ra 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ố và TV tương tự dựa trên các tiêu chuẩn phát sóng chính.
Thành phần
Đối với Android 11, 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 Tuner SDK: Giao diện giữa khung và ứng dụng
- Trình quản lý tài nguyên bộ chỉnh (TRM): Điều phối tài nguyên HW của bộ chỉnh
Đố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ụ Trình quản lý thiết bị đầu vào TV (TIMS)MediaCodec
hoặc bộ mã hoá và giải mã nội dung nghe nhìnAudioTrack
hoặc bản âm thanhMediaResourceManager
hoặc trình quản lý tài nguyên đa phương tiện (MRM)
Hình 1. 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 bên dưới.
- 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 bên dưới.
- DTMB
Demux hỗ trợ các giao thức truyền phát trực tiếp dưới đây.
- Luồng truyền tải (TS)
- Giao thức truyền tải nội dung nghe nhì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)
Bộ giải mã hỗ trợ các biện pháp bảo vệ nội dung dưới đây.
- Đường dẫn an toàn cho nội dung nghe nhìn
- Xoá đường dẫn đến nội dung nghe nhìn
- Bản ghi cục bộ an toàn
- Phát nội dung an toàn trên thiết bị
API bộ chỉnh hỗ trợ các trường hợp sử dụng dưới đây.
- Quét
- Tính năng Live
- Phát
- Ghi âm
Tuner, MediaCodec
và AudioTrack
hỗ trợ các chế độ luồng dữ liệu bên dưới.
- Tải trọng ES có vùng đệm bộ nhớ rõ ràng
- Tải trọng ES có mã nhận dạng bộ nhớ bảo mật
- Chế độ thực tế
Thiết kế tổng thể
HAL của bộ chỉnh đượ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 ở 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, bộ tách kênh và bộ giải mã sang khung thông qua các giao diện
IFrontend
,IDemux
,IDescrambler
,IFilter
,IDvr
vàILnb
. - 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ư
MediaCodec
vàAudioTrack
.
Một lớp Java Tuner 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 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 Native Tuner 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ộ chỉnh kênh 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ừ các ứng dụng. Quy tắc mặc định là nền trước thắng.
CAS đa phương tiện và CAS HAL được cải tiến bằng 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ư việc tháo và lắp CICAM.
- Tích hợp với Tuner HAL bằng cách cung cấp các mã thông báo khoá.
MediaCodec
và AudioTrack
được cải tiến bằng các tính năng bên dưới.
- 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á phần cứng A/V trong quá trình phát qua đường hầm.
- Đã định cấu hình chế độ hỗ trợ cho
ES_payload
và chế độ truyền qua.
Hình 2. Sơ đồ các thành phần trong Tuner HAL
Quy trình tổng thể
Các sơ đồ dưới đây minh hoạ trình tự gọi để phát nội dung phát sóng trực tiếp.
Thiết lậ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
Hình 4. Xử lý A/V để phát nội dung phát sóng trực tiếp
Xử lý nội dung bị xáo trộn
Hình 5. Xử lý nội dung bị xáo trộn khi phát lại chương trình phát sóng trực tiếp
Xử lý dữ liệu âm thanh/hình ảnh
Hình 6. Đang xử lý nội dung nghe nhìn để phát sóng trực tiếp
Tuner SDK API
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 Tuner SDK API để 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à demux là các thành phần nội bộ.
Hình 7. 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. Đâ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 tối thiểu bắt buộc trong tài liệu về các API mới của Android 12.
Gói
API Tuner SDK cung cấp 4 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
Hình 8. Các gói API Tuner SDK
Android.media.tv.tuner
Gói Tuner là một đ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 thậ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ốuseCase
vàsessionId
.tune()
: Nhận tài nguyên và điều chỉnh giao diện người dùng bằng cách chỉ định tham sốFrontendSetting
.openFilter()
: Lấy một thực thể bộ lọc bằng cách chỉ định loại bộ lọc.openDvrRecorder()
: Lấy một phiên bản ghi bằng cách chỉ định kích thước vùng đệm.openDvrPlayback()
: Nhận một phiên phát bằng cách chỉ định kích thước vùng đệm.openDescrambler()
: Nhận một thực thể bộ giải mã.openLnb()
: Nhận một phiên bản LNB nội bộ.openLnbByName()
: Nhận một phiên bản LNB bên ngoài.openTimeFilter()
: Nhận một thực thể bộ lọc thời gian.
Gói Tuner 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 này đượ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 bộ sưu tậ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ừ nhiều tiêu chuẩn DTV bằng các lớp bên dưới.
AnalogFrontendSettings
Atsc3FrontendSettings
AtscFrontendSettings
DvbcFrontendSettings
DvbsFrontendSettings
DvbtFrontendSettings
Isdbs3FrontendSettings
IsdbsFrontendSettings
IsdbtFrontendSettings
Từ Android 12 trở lên với Tuner HAL 1.1 trở lên, hệ thống sẽ hỗ trợ tiêu chuẩn DTV sau đây.
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 trở lên với Tuner HAL 1.1 trở lên, hệ thống sẽ hỗ trợ tiêu chuẩn DTV sau đây.
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ý các 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ể và tạo 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 chính xác về 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 khác (ví dụ: mã nhận dạng PLD), thì bạn nên chọn Tuner.tune
vì đây là lựa chọ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 sẵn thông tin bắt buộc vào
FrontendSettings
bằng cách sử dụngTuner.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ố tiếp theo có trong danh sách tần số.
TIS sẽ gọi lại Tuner.tune
cho đến khi hết tất cả cá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 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ì 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 sẽ xảy ra:
TIS sử dụng
Tuner.scan(AUTO_SCAN)
vớiFrontendSettings
được điền tần suất.HAL báo cáo các thông báo quét
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
cho HAL để tiếp tục chế độ cài đặt tiếp theo trên cùng một tần số. Nếu cấu trúcFrontendSettings
trống, HAL sẽ sử dụng chế độ cài đặt có sẵn tiếp theo. Nếu không, HAL sẽ dùngFrontendSettings
cho một lần quét và gửiEND
để cho biết 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 thao tác quét đã hoàn tất.TIS sẽ chuyển sang tần số tiếp theo có trong danh sách tần số.
TIS sẽ gọi lại Tuner.scan(AUTO_SCAN)
cho đến khi hết tất cả cá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á trình quét.
Tuner.scan(BLIND_SCAN)
Nếu TIS không có danh sách tần số và Vendor HAL 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ì bạn nên dùng Tuner.scan(BLIND_SCAN)
.
- TIS sử dụng
Tuner.scan(BLIND_SCAN)
. Bạn có thể chỉ định tần suất trongFrontendSettings
cho tần suất bắt đầu, nhưng TIS sẽ bỏ qua các chế độ cài đặt khác trongFrontendSettings
. - 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 sẽ 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 số mà không cần TIS làm gì cả.
HAL báo cáo
PROGRESS
.
TIS sẽ gọi lại Tuner.scan(AUTO_SCAN)
cho đến khi hết tất cả cá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 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.
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 để xem danh sách đầy đủ các thao tác.
configure()
start()
stop()
flush()
read()
Hãy tham khảo mã nguồn Android để xem 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. Đây là chế độ cài đặt 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 trở lên với 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
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: |
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 trình nội bộ, hãy chạy một hoặc nhiều lần. Filter.read(buffer, offset, adjustedSize) 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 được lắp ráp sẽ được điền vào FMQ bằng một gói phiên khác. |
isRaw: |
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++ 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: |
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 trình nội bộ, hãy chạy một hoặc nhiều lần. Filter.read(buffer, offset, adjustedSize) 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 được lắp ráp sẽ được điền vào FMQ bằng một gói PES khác. |
isRaw: |
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++ 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: |
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 trình nội bộ, hãy chạy một hoặc nhiều lần. Filter.read(buffer, offset, adjustedSize) 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 sẽ được một gói MFU khác điền vào FMQ. |
isRaw: |
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++ 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: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
Theo sự kiện và lịch trình nội bộ, hãy chạy một hoặc nhiều lần. Filter.read(buffer, offset, adjustedSize) Dữ liệu được sao chép từ MQ của HAL vào vùng đệm ứng dụng. |
ts bị lọc ra có tiêu đề ts được điền vào FMQ. |
TS.Audio TS.Video MMTP.Audio MMTP.Video |
isPassthrough: |
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: |
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++ Cách sử dụng tính năng Âm thanh trực tiếp của AudioTrack :for i=0; i<n; i++ |
Dữ liệu ES hoặc 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
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++ Đối với nội dung đã ghi hình, theo RecordStatus::* và lịch trình nội bộ, hãy làm một trong những việc sau:
|
Đối với dữ liệu chỉ mục: Được truyền trong tải trọng sự kiện. Đối với nội dung được ghi hình: Luồng TS được ghép kênh 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++ |
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 trình nội bộ, hãy chạy một hoặc nhiều lần. Filter.read(buffer, offset, adjustedSize) Dữ liệu được sao chép từ MQ của HAL vào vùng đệm ứng dụng. |
mmtp bị lọc ra 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++ Đối với nội dung được ghi lại, theo RecordStatus::* và lịch trình nội bộ, hãy làm một trong những việc sau:
|
Đối với dữ liệu chỉ mục: Được truyền trong tải trọng sự kiện. Đối với nội dung được ghi hình: Luồng được ghi hình kết hợp được điền vào FMQ. Nếu nguồn bộ lọc để ghi là TLV.TLV đến IP.IP có truyền qua, thì luồng được ghi sẽ có một 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 tải trọng IP được điền vào FMQ bằng một gói tải trọng IP khác. |
IP.IP TLV.TLV ALP.ALP |
isPassthrough: |
Không bắt buộc:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
Luồng con 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: |
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 trình nội bộ, hãy chạy một hoặc nhiều lần. Filter.read(buffer, offset, adjustedSize) Dữ liệu được sao chép từ MQ của HAL vào vùng đệm ứng dụng. |
Luồng con giao thức được lọ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 |
Tải trọng 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
Hình 10. Quy trình tạo PSI/SI
Mở một bộ lọc.
Filter filter = tuner.openFilter( Filter.TYPE_TS, Filter.SUBTYPE_SECTION, /* bufferSize */1000, executor, filterCallback );
Đị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();
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); } } } };
Ví dụ về luồng sử dụng MediaEvent từ bộ lọc
Hình 11. Luồng dữ liệu để sử dụng MediaEvent từ bộ lọc
- Mở, định cấu hình và khởi động bộ lọc A/V.
- Xử lý
MediaEvent
. - Nhận
MediaEvent
. - Xếp hàng khối tuyến tính vào
codec
. - Giải phóng đối tượng 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 DvrRecorder
và DvrPlayback
.
OnPlaybackStatusChangedListener
và OnRecordStatusChangedListener
được dùng để báo cáo trạng thái của một phiên bản DVR.
Ví dụ về quy trình bắt đầu ghi
Hình 12. Quy trình bắt đầu ghi
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();
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. } } } };
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); } } };
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. Các nhà cung cấp sử dụng giao diện này để triển khai Tuner HAL và khung này sử dụng giao diện đó để giao tiếp với việc 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ế độ kiểm soát 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 (xuất phát từ Tuner HAL 1.0)
Mô-đun | Các thao tác điều khiển cơ bản | Các chế độ kiểm soát 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 |
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
HAL của bộ dò sóng 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.
- Các bộ lọc được liên kết dưới dạng một 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ả các bộ lọc đều bắt đầu nhận dữ liệu.
- Mối liên kết bộ lọc sẽ xoá bộ lọc cuối cùng.
Khối mã bên dưới và Hình 14 minh hoạ một ví dụ về việc 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>)
}
Hình 14. Lưu đồ về 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 Tuner Resource Manager (TRM), việc chuyển đổi giữa 2 ứ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ế "giành quyền truy cập đầu tiên", tức là ứng dụng nào nhận được tài nguyên trước tiên sẽ giữ 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 một dịch vụ hệ thống để quản lý các tài nguyên phần cứng Tuner, TVInput
và CAS cho các ứng dụng. TRM sử dụng cơ chế "thắng ở nền trước", cơ chế này 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 và loại trường hợp sử dụng của ứng 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 và DVR.
Giao diện TRM
TRM cung cấp các giao diện AIDL trong ITunerResourceManager.aidl
cho khung Tuner, MediaCas
và TvInputHardwareManager
để đă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ý khách hàng.
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à phát hành 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 máy khách 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 thông số trong hồ sơ của ứng dụng và giá trị ưu tiên trong 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.
Các tham số trong hồ sơ của ứng dụng khách
TRM truy xuất mã nhận dạng quy trình từ mTvInputSessionId
để quyết định xem một ứng dụng có phải là ứng dụng nền trước hay ứng dụng nền. Để tạo mTvInputSessionId
, TvInputService.onCreateSession
hoặc TvInputService.onCreateRecordingSession
, hãy khởi động 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ê 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 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 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ể 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 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 tuỳ ý và giá trị nice
TRM cung cấp updateClientPriority
để ứng dụng cập nhật giá trị ưu tiên tuỳ ý và giá trị tốt.
Giá trị ưu tiên tuỳ ý sẽ ghi đè giá trị ưu tiên được tính từ loại trường hợp sử dụng và mã phiên.
Giá trị nice cho biết mức độ khoan dung của hành vi của ứng dụng khi xung đột với một ứng dụng khác. Giá trị nice sẽ 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ó.
Cơ chế xác nhận quyền sở hữu lại
Sơ đồ dưới đây cho thấy cách tài nguyên được thu hồi và chỉ định khi xảy ra xung đột tài nguyên.
Hình 15. Sơ đồ cơ chế thu hồi đối với xung đột giữa các tài nguyên của Bộ chỉnh kênh