Tính năng tạo đường hầm đa phương tiện cho phép dữ liệu video nén truyền qua một phần cứng bộ giải mã video trực tiếp lên màn hình mà không cần được xử lý bằng mã ứng dụng hoặc Mã khung Android. Mã dành riêng cho thiết bị bên dưới ngăn xếp Android xác định khung hình video để gửi đến màn hình và thời điểm gửi bằng so sánh dấu thời gian trình chiếu khung hình video với một trong các dấu thời gian sau các loại đồng hồ bên trong:
Để phát video theo yêu cầu trong Android 5 trở lên,
AudioTrack
đồng hồ đã đồng bộ hoá với dấu thời gian trình bày âm thanh đã vượt qua trong ứng dụngĐể phát nội dung phát sóng trực tiếp trên Android 11 trở lên, đồng hồ tham chiếu chương trình (PCR) hoặc đồng hồ thời gian hệ thống (STC) được điều khiển bởi điều chỉnh
Thông tin khái quát
Phát lại video truyền thống trên Android thông báo
ứng dụng khi khung video nén đã được giải mã. Sau đó, ứng dụng
bản phát hành
khung video đã giải mã lên màn hình để kết xuất tại cùng một đồng hồ hệ thống
làm khung âm thanh tương ứng.
truy xuất dữ liệu trong quá khứ
AudioTimestamps
thực thể để tính toán thời gian chính xác.
Do việc phát video trong đường hầm bỏ qua mã ứng dụng và giảm số lần các quá trình tác động lên video, nó có thể kết xuất video hiệu quả hơn tuỳ thuộc vào cách triển khai của OEM (Nhà sản xuất thiết bị gốc). Tính năng này cũng có thể cung cấp video chính xác hơn nhịp độ và đồng bộ với đồng hồ đã chọn (PRC, STC hoặc âm thanh) bằng cách tránh các vấn đề về thời gian do sai lệch tiềm ẩn giữa thời gian của Android để kết xuất video và thời gian thực thi vsync phần cứng. Tuy nhiên, cũng có thể làm giảm khả năng hỗ trợ hiệu ứng GPU như làm mờ hoặc các góc tròn trong cửa sổ hình trong hình (PiP) vì các vùng đệm bỏ qua ngăn xếp đồ hoạ Android.
Sơ đồ dưới đây cho thấy cách đường hầm đơn giản hoá quá trình phát video.
Hình 1. So sánh quy trình phát video truyền thống và qua đường hầm
Dành cho nhà phát triển ứng dụng
Vì hầu hết các nhà phát triển ứng dụng đều tích hợp với thư viện để phát lại trong hầu hết các trường hợp, việc triển khai chỉ yêu cầu định cấu hình lại để phát trong đường hầm. Để triển khai video được tạo đường hầm ở cấp thấp trình phát, hãy làm theo các hướng dẫn sau.
Đối với tính năng phát video theo yêu cầu trên Android 5 trở lên:
Tạo một thực thể
SurfaceView
.Tạo một thực thể
audioSessionId
.Tạo thực thể
AudioTrack
vàMediaCodec
bằngaudioSessionId
thực thể được tạo ở bước 2.Thêm dữ liệu âm thanh vào danh sách chờ
AudioTrack
bằng dấu thời gian trình bày của khung âm thanh đầu tiên trong dữ liệu âm thanh.
Để phát sự kiện phát sóng trực tiếp trên Android 11 trở lên, hãy làm như sau:
Tạo một thực thể
SurfaceView
.Nhận một thực thể
avSyncHwId
từTuner
.Tạo thực thể
AudioTrack
vàMediaCodec
bằng thực thểavSyncHwId
tạo ở bước 2.
Luồng lệnh gọi API được thể hiện trong các đoạn mã sau:
aab.setContentType(AudioAttributes.CONTENT_TYPE_MOVIE);
// configure for audio clock sync
aab.setFlag(AudioAttributes.FLAG_HW_AV_SYNC);
// or, for tuner clock sync (Android 11 or higher)
new tunerConfig = TunerConfiguration(0, avSyncId);
aab.setTunerConfiguration(tunerConfig);
if (codecName == null) {
return FAILURE;
}
// configure for audio clock sync
mf.setInteger(MediaFormat.KEY_AUDIO_SESSION_ID, audioSessionId);
// or, for tuner clock sync (Android 11 or higher)
mf.setInteger(MediaFormat.KEY_HARDWARE_AV_SYNC_ID, avSyncId);
Hành vi khi phát video theo yêu cầu
Vì việc phát video theo yêu cầu được tạo trong đường hầm được liên kết ngầm với AudioTrack
thì hành vi phát video qua đường hầm có thể phụ thuộc vào hành vi đó
phát lại âm thanh.
Theo mặc định, trên hầu hết các thiết bị, khung hình video sẽ không hiển thị cho đến khi có âm thanh sẽ bắt đầu phát. Tuy nhiên, ứng dụng có thể cần kết xuất khung hình video trước bắt đầu phát âm thanh (chẳng hạn như để hiển thị cho người dùng video hiện tại) vị trí trong khi tua.
Để báo hiệu rằng khung hình video đầu tiên trong hàng đợi sẽ hiển thị ngay khi mã đó được giải mã, hãy đặt
PARAMETER_KEY_TUNNEL_PEEK
thành1
. Khi khung hình video nén được sắp xếp lại trong hàng đợi (chẳng hạn như khi Khung B điều này có nghĩa là khung video hiển thị đầu tiên phải luôn là Khung hình chữ I.Nếu bạn không muốn khung hình video đầu tiên trong hàng đợi hiển thị cho đến khi có âm thanh bắt đầu phát, hãy đặt tham số này thành
0
.Nếu bạn không đặt thông số này, OEM sẽ xác định hành vi của thiết bị.
Khi bạn không cung cấp dữ liệu âm thanh cho
AudioTrack
và vùng đệm trống (chạy âm thanh), ngăn phát video cho đến khi ghi thêm dữ liệu âm thanh vì đồng hồ âm thanh không còn tua nữa.Trong khi phát, những lần gián đoạn mà ứng dụng không thể khắc phục có thể xuất hiện sau dấu thời gian trình bày âm thanh. Khi điều này xảy ra, OEM sẽ khắc phục các lỗi âm các khoảng trống bằng cách làm gián đoạn khung hình video hiện tại và các khoảng trống tích cực bằng cách giảm khung video hoặc chèn khung âm thanh im lặng (tuỳ thuộc vào OEM (Nhà sản xuất thiết bị gốc) triển khai). Vị trí khung hình
AudioTimestamp
không tăng đối với đã chèn khung âm thanh im lặng.
Dành cho nhà sản xuất thiết bị
Cấu hình
OEM phải tạo một bộ giải mã video riêng để hỗ trợ phát video theo đường hầm.
Bộ giải mã này nên quảng cáo rằng nó có khả năng phát theo đường hầm trong
Tệp media_codecs.xml
:
<Feature name="tunneled-playback" required="true"/>
Khi một thực thể MediaCodec
được tạo trong đường hầm được định cấu hình bằng mã phiên âm thanh, thực thể đó
truy vấn AudioFlinger
cho mã HW_AV_SYNC
này:
if (entry.getKey().equals(MediaFormat.KEY_AUDIO_SESSION_ID)) {
int sessionId = 0;
try {
sessionId = (Integer)entry.getValue();
}
catch (Exception e) {
throw new IllegalArgumentException("Wrong Session ID Parameter!");
}
keys[i] = "audio-hw-sync";
values[i] = AudioSystem.getAudioHwSyncForSession(sessionId);
}
Trong truy vấn này,
AudioFlinger
truy xuất mã nhận dạng HW_AV_SYNC
từ thiết bị âm thanh chính và liên kết nội bộ thiết bị này với âm thanh
ID phiên:
audio_hw_device_t *dev = mPrimaryHardwareDev->hwDevice();
char *reply = dev->get_parameters(dev, AUDIO_PARAMETER_HW_AV_SYNC);
AudioParameter param = AudioParameter(String8(reply));
int hwAVSyncId;
param.getInt(String8(AUDIO_PARAMETER_HW_AV_SYNC), hwAVSyncId);
Nếu một thực thể AudioTrack
đã được tạo, thì mã nhận dạng HW_AV_SYNC
sẽ là
được truyền đến luồng đầu ra có cùng mã phiên âm thanh. Nếu chưa được
chưa được tạo, thì mã nhận dạng HW_AV_SYNC
sẽ được truyền đến luồng đầu ra trong khoảng thời gian
Tạo AudioTrack
. Điều này được thực hiện bằng cách phát lại
chuỗi:
mOutput->stream->common.set_parameters(&mOutput->stream->common, AUDIO_PARAMETER_STREAM_HW_AV_SYNC, hwAVSyncId);
Mã nhận dạng HW_AV_SYNC
, cho dù tương ứng với luồng đầu ra âm thanh hay
Tuner
, được chuyển vào thành phần OMX hoặc Codec2 để
Mã OEM có thể liên kết bộ mã hoá và giải mã với luồng đầu ra âm thanh tương ứng hoặc
luồng bộ dò.
Trong quá trình định cấu hình thành phần, thành phần OMX hoặc Codec2 phải trả về một
trình xử lý băng tần phụ có thể dùng để liên kết bộ mã hoá và giải mã với một Trình soạn thảo phần cứng
(HWC). Khi ứng dụng liên kết một nền tảng với MediaCodec
, băng tần phụ này
tên người dùng được truyền xuống HWC thông qua SurfaceFlinger
, giúp định cấu hình
xếp lớp dưới dạng
Lớp side Band.
err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle);
if (err != OK) {
ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).", sidebandHandle, err);
return err;
}
HWC chịu trách nhiệm nhận vùng đệm hình ảnh mới từ đầu ra của bộ mã hoá và giải mã tại thời gian thích hợp, được đồng bộ hoá với luồng đầu ra âm thanh liên quan hoặc đồng hồ tham chiếu chương trình bộ chỉnh, kết hợp vùng đệm với nội dung của các lớp khác và hiển thị hình ảnh thu được. Điều này xảy ra độc lập với chu kỳ chuẩn bị và thiết lập thông thường. Cuộc gọi chuẩn bị và thiết lập chỉ xảy ra khi các lớp khác thay đổi hoặc khi thuộc tính của lớp băng tần phụ (chẳng hạn như vị trí hoặc kích thước).
OMX
Thành phần bộ giải mã được tạo đường hầm phải hỗ trợ những nội dung sau:
Đã mở rộng việc thiết lập
OMX.google.android.index.configureVideoTunnelMode
tham số này, sử dụng cấu trúcConfigureVideoTunnelModeParams
để truyền trong mã nhận dạngHW_AV_SYNC
liên kết với thiết bị đầu ra âm thanh.Định cấu hình tham số
OMX_IndexConfigAndroidTunnelPeek
cho biết bộ mã hoá và giải mã kết xuất hoặc không kết xuất khung video được giải mã đầu tiên, bất kể đã bắt đầu phát âm thanh hay chưa.Gửi sự kiện
OMX_EventOnFirstTunnelFrameReady
khi đường hầm đầu tiên khung video đã được giải mã và sẵn sàng để được hiển thị.
Phương thức triển khai AOSP định cấu hình chế độ đường hầm trong
ACodec
qua
OMXNodeInstance
như minh hoạ trong đoạn mã sau:
OMX_INDEXTYPE index;
OMX_STRING name = const_cast<OMX_STRING>(
"OMX.google.android.index.configureVideoTunnelMode");
OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
ConfigureVideoTunnelModeParams tunnelParams;
InitOMXParams(&tunnelParams);
tunnelParams.nPortIndex = portIndex;
tunnelParams.bTunneled = tunneled;
tunnelParams.nAudioHwSync = audioHwSync;
err = OMX_SetParameter(mHandle, index, &tunnelParams);
err = OMX_GetParameter(mHandle, index, &tunnelParams);
sidebandHandle = (native_handle_t*)tunnelParams.pSidebandWindow;
Nếu thành phần hỗ trợ cấu hình này, thành phần nên phân bổ băng tần phụ
xử lý đến bộ mã hoá và giải mã này rồi truyền lại qua thành phần pSidebandWindow
để
mà HWC có thể xác định bộ mã hoá và giải mã được liên kết. Nếu thành phần này không
hỗ trợ cấu hình này, thì tệp sẽ đặt bTunneled
thành OMX_FALSE
.
Bộ mã hoá và giải mã 2
Trên Android 11 trở lên, Codec2
hỗ trợ tính năng phát theo đường hầm. Bộ giải mã
thành phần phải hỗ trợ những nội dung sau:
Định cấu hình
C2PortTunneledModeTuning
để định cấu hình chế độ đường hầm và truyền trongHW_AV_SYNC
được truy xuất từ thiết bị đầu ra âm thanh hoặc cấu hình bộ dò.Truy vấn
C2_PARAMKEY_OUTPUT_TUNNEL_HANDLE
để phân bổ và truy xuất thanh điều khiển bên cạnh cho HWC.Xử lý
C2_PARAMKEY_TUNNEL_HOLD_RENDER
khi được đính kèm vớiC2Work
. hướng dẫn bộ mã hoá và giải mã giải mã và báo hiệu về việc hoàn thành công việc nhưng không hiển thị vùng đệm đầu ra cho đến khi 1) bộ mã hoá và giải mã được hướng dẫn kết xuất hoặc 2) bắt đầu phát âm thanh.Xử lý
C2_PARAMKEY_TUNNEL_START_RENDER
để hướng dẫn bộ mã hoá và giải mã ngay lập tức hiển thị khung được đánh dấu bằngC2_PARAMKEY_TUNNEL_HOLD_RENDER
, ngay cả khi quá trình phát âm thanh chưa bắt đầu.Hãy để
debug.stagefright.ccodec_delayed_params
chưa định cấu hình (nên dùng). Nếu bạn định cấu hình nó, đặt thànhfalse
.
Phương thức triển khai AOSP định cấu hình chế độ đường hầm trong
CCodec
thông qua C2PortTunnelModeTuning
, như minh hoạ trong đoạn mã sau:
if (msg->findInt32("audio-hw-sync", &tunneledPlayback->m.syncId[0])) {
tunneledPlayback->m.syncType =
C2PortTunneledModeTuning::Struct::sync_type_t::AUDIO_HW_SYNC;
} else if (msg->findInt32("hw-av-sync-id", &tunneledPlayback->m.syncId[0])) {
tunneledPlayback->m.syncType =
C2PortTunneledModeTuning::Struct::sync_type_t::HW_AV_SYNC;
} else {
tunneledPlayback->m.syncType =
C2PortTunneledModeTuning::Struct::sync_type_t::REALTIME;
tunneledPlayback->setFlexCount(0);
}
c2_status_t c2err = comp->config({ tunneledPlayback.get() }, C2_MAY_BLOCK,
failures);
std::vector<std::unique_ptr<C2Param>> params;
c2err = comp->query({}, {C2PortTunnelHandleTuning::output::PARAM_TYPE},
C2_DONT_BLOCK, ¶ms);
if (c2err == C2_OK && params.size() == 1u) {
C2PortTunnelHandleTuning::output *videoTunnelSideband =
C2PortTunnelHandleTuning::output::From(params[0].get());
return OK;
}
Nếu thành phần hỗ trợ cấu hình này, thành phần nên phân bổ băng tần phụ
xử lý đến bộ mã hoá và giải mã này rồi truyền lại qua C2PortTunnelHandlingTuning
để
mà HWC có thể xác định bộ mã hoá và giải mã được liên kết.
Lớp trừu tượng phần cứng (HAL) cho âm thanh
Để phát video theo yêu cầu, HAL âm thanh nhận bản trình bày âm thanh dấu thời gian cùng dòng với dữ liệu âm thanh ở định dạng Big-endian bên trong một tiêu đề ở đầu mỗi khối dữ liệu âm thanh mà ứng dụng ghi:
struct TunnelModeSyncHeader {
// The 32-bit data to identify the sync header (0x55550002)
int32 syncWord;
// The size of the audio data following the sync header before the next sync
// header might be found.
int32 sizeInBytes;
// The presentation timestamp of the first audio sample following the sync
// header.
int64 presentationTimestamp;
// The number of bytes to skip after the beginning of the sync header to find the
// first audio sample (20 bytes for compressed audio, or larger for PCM, aligned
// to the channel count and sample size).
int32 offset;
}
Để HWC kết xuất khung hình video đồng bộ với các khung âm thanh tương ứng, HAL âm thanh phải phân tích cú pháp tiêu đề đồng bộ hoá và sử dụng dấu thời gian trình bày để đồng bộ hoá lại đồng hồ phát với kết xuất âm thanh. Để đồng bộ hoá lại khi đang phát âm thanh nén, HAL âm thanh có thể cần phân tích cú pháp siêu dữ liệu bên trong dữ liệu âm thanh nén để xác định thời lượng phát.
Tạm dừng hỗ trợ
Android 5 trở xuống không có tính năng hỗ trợ tạm dừng. Bạn có thể tạm dừng đường hầm chỉ phát bằng tình trạng thiếu A/V, nhưng nếu bộ đệm nội bộ cho video lớn (ví dụ: có 1 giây dữ liệu trong thành phần OMX), thành phần này sẽ tạm dừng trông không thích ứng.
Trên Android 5.1 trở lên, AudioFlinger
hỗ trợ tính năng tạm dừng và tiếp tục để quay video trực tiếp
đầu ra âm thanh (phát âm thanh). Nếu HAL (Lớp trừu tượng phần cứng) triển khai thao tác tạm dừng và tiếp tục, hãy theo dõi lượt tạm dừng
và sơ yếu lý lịch sẽ được chuyển tiếp đến HAL.
Trình tự cuộc gọi tạm dừng, xả nước, tiếp tục được tuân thủ bằng cách thực thi lệnh gọi HAL trong luồng phát (tương tự như giảm tải).
Đề xuất triển khai
Lớp trừu tượng phần cứng (HAL) cho âm thanh
Đối với Android 11, bạn có thể dùng mã nhận dạng đồng bộ hoá HW từ PCR hoặc STC để đồng bộ hoá A/V, vì vậy chỉ hỗ trợ luồng video.
Đối với Android 10 trở xuống, các thiết bị hỗ trợ tính năng phát video theo đường hầm phải:
ít nhất một cấu hình luồng đầu ra âm thanh có FLAG_HW_AV_SYNC
và
AUDIO_OUTPUT_FLAG_DIRECT
gắn cờ trong tệp audio_policy.conf
của nó. Những cờ này
được dùng để đặt xung nhịp hệ thống từ đồng hồ âm thanh.
OMX
Nhà sản xuất thiết bị nên có một thành phần OMX riêng cho video được tạo đường hầm phát video (nhà sản xuất có thể sử dụng thêm các thành phần OMX cho các loại phát âm thanh và video, chẳng hạn như phát lại an toàn). Thành phần được tạo đường hầm nên:
Chỉ định 0 vùng đệm (
nBufferCountMin
,nBufferCountActual
) trên dữ liệu đầu ra cổng.Triển khai phần mở rộng
OMX.google.android.index.prepareForAdaptivePlayback setParameter
.Chỉ định chức năng của lớp đó trong tệp
media_codecs.xml
rồi khai báo tính năng phát theo đường hầm. Nội dung này cũng nêu rõ mọi giới hạn về khung hình kích thước, căn chỉnh hoặc tốc độ bit. Sau đây là ví dụ minh hoạ:<MediaCodec name="OMX.OEM_NAME.VIDEO.DECODER.AVC.tunneled" type="video/avc" > <Feature name="adaptive-playback" /> <Feature name="tunneled-playback" required=”true” /> <Limit name="size" min="32x32" max="3840x2160" /> <Limit name="alignment" value="2x2" /> <Limit name="bitrate" range="1-20000000" /> ... </MediaCodec>
Nếu thành phần OMX đó được dùng để hỗ trợ giải mã theo đường hầm và không theo đường hầm, thì tính năng phát theo đường hầm sẽ là không bắt buộc. Cả đường hầm và thì bộ giải mã không truyền dữ liệu có cùng những giới hạn về khả năng. Ví dụ: được hiển thị bên dưới:
<MediaCodec name="OMX._OEM\_NAME_.VIDEO.DECODER.AVC" type="video/avc" >
<Feature name="adaptive-playback" />
<Feature name="tunneled-playback" />
<Limit name="size" min="32x32" max="3840x2160" />
<Limit name="alignment" value="2x2" />
<Limit name="bitrate" range="1-20000000" />
...
</MediaCodec>
Trình soạn phần cứng (HWC)
Khi có một lớp được tạo đường hầm (một lớp có HWC_SIDEBAND
compositionType
) đang bật
một màn hình, sidebandStream
của lớp là xử lý băng tần cạnh được phân bổ bởi
thành phần video OMX.
HWC đồng bộ hoá các khung video đã giải mã (từ thành phần OMX được tạo đường hầm) đến
bản âm thanh được liên kết (có mã audio-hw-sync
). Khi một khung hình video mới
trở nên hiện hành, HWC kết hợp nó với nội dung hiện tại của tất cả các lớp
nhận được trong cuộc gọi chuẩn bị hoặc đặt lịch gần nhất và hiển thị hình ảnh thu được.
Lệnh gọi chuẩn bị hoặc lệnh gọi chỉ diễn ra khi các lớp khác thay đổi hoặc khi
các thuộc tính của lớp dải bên (chẳng hạn như vị trí hoặc kích thước) thay đổi.
Hình sau đây biểu thị HWC hoạt động với phần cứng (hoặc kernel hay trình điều khiển) để kết hợp các khung hình video (7b) với cấu trúc mới nhất (7a) để hiển thị đúng thời điểm, dựa trên âm thanh (7c).
Hình 2. Bộ đồng bộ hoá phần cứng (hoặc nhân hệ điều hành) hoặc trình điều khiển của HWC