การเชื่อมต่อมัลติมีเดียช่วยให้ข้อมูลวิดีโอที่บีบอัดสามารถเชื่อมต่อผ่านตัวถอดรหัสวิดีโอฮาร์ดแวร์ไปยังจอแสดงผลได้โดยตรง โดยไม่ต้องประมวลผลด้วยโค้ดแอปหรือโค้ดเฟรมเวิร์ก Android โค้ดเฉพาะอุปกรณ์ที่อยู่ใต้สแต็ก Android จะกำหนดเฟรมวิดีโอที่จะส่งไปยังจอแสดงผลและเวลาที่จะส่งโดย การเปรียบเทียบการประทับเวลาการนำเสนอเฟรมวิดีโอกับนาฬิกาภายในประเภทใดประเภทหนึ่งต่อไปนี้
สำหรับการเล่นวิดีโอแบบออนดีมานด์ใน Android 5 ขึ้นไป แอปจะต้อง
AudioTrack
ส่งนาฬิกาที่ซิงค์กับแสตมป์เวลาของงานนำเสนอเสียงสำหรับการเล่นการออกอากาศสดใน Android 11 ขึ้นไป นาฬิกาอ้างอิงโปรแกรม (PCR) หรือนาฬิกาเวลาของระบบ (STC) ที่ขับเคลื่อนโดย จูนเนอร์
ฉากหลัง
การเล่นวิดีโอแบบเดิมใน Android จะแจ้ง
แอปเมื่อถอดรหัสเฟรมวิดีโอที่บีบอัดแล้ว จากนั้นแอปจะปล่อยเฟรมวิดีโอที่ถอดรหัสแล้วไปยังจอแสดงผลเพื่อแสดงผลในเวลาเดียวกันกับนาฬิกาของระบบ
กับเฟรมเสียงที่เกี่ยวข้อง
เรียกอินสแตนซ์AudioTimestamps
ในอดีต
เพื่อคำนวณเวลาที่ถูกต้อง
เนื่องจากการเล่นวิดีโอแบบ Tunnel จะข้ามโค้ดของแอปและลดจำนวน กระบวนการที่ทำงานกับวิดีโอ จึงทำให้การแสดงวิดีโอมีประสิทธิภาพมากขึ้น ขึ้นอยู่กับการติดตั้งใช้งานของ OEM นอกจากนี้ ยังช่วยให้จังหวะและ การซิงค์วิดีโอมีความแม่นยำมากขึ้นกับนาฬิกาที่เลือก (PRC, STC หรือเสียง) โดยหลีกเลี่ยง ปัญหาด้านเวลาที่อาจเกิดจากความคลาดเคลื่อนระหว่างเวลาที่คำขอของ Android ในการแสดงวิดีโอและเวลาของ Vsync ของฮาร์ดแวร์จริง อย่างไรก็ตาม การทำอุโมงค์ยังอาจลดการรองรับเอฟเฟกต์ GPU เช่น การเบลอ หรือมุมโค้งในหน้าต่างการแสดงภาพซ้อนภาพ (PiP) เนื่องจากบัฟเฟอร์ จะข้ามสแต็กกราฟิกของ Android
แผนภาพต่อไปนี้แสดงให้เห็นว่าการทำอุโมงค์ช่วยลดความซับซ้อนของกระบวนการเล่นวิดีโอได้อย่างไร
รูปที่ 1 การเปรียบเทียบกระบวนการเล่นวิดีโอแบบดั้งเดิมและแบบอุโมงค์
สำหรับนักพัฒนาแอป
เนื่องจากนักพัฒนาแอปส่วนใหญ่ผสานรวมกับไลบรารีสำหรับการใช้งานการเล่น ดังนั้นในกรณีส่วนใหญ่ การใช้งานจึงต้องกำหนดค่าไลบรารีนั้นใหม่สำหรับการเล่นแบบอุโมงค์เท่านั้น หากต้องการติดตั้งใช้งานวิดีโอเพลเยอร์ที่ส่งผ่านอุโมงค์ในระดับต่ำ ให้ทำตามวิธีการต่อไปนี้
หากต้องการเล่นวิดีโอแบบออนดีมานด์ใน Android 5 ขึ้นไป ให้ทำดังนี้
สร้างอินสแตนซ์
SurfaceView
สร้างอินสแตนซ์
audioSessionId
สร้างอินสแตนซ์
AudioTrack
และMediaCodec
ด้วยอินสแตนซ์audioSessionId
ที่สร้างในขั้นตอนที่ 2จัดคิวข้อมูลเสียงไปยัง
AudioTrack
พร้อมการประทับเวลาการนำเสนอสำหรับ เฟรมเสียงแรกในข้อมูลเสียง
หากต้องการเล่นการออกอากาศสดใน Android 11 ขึ้นไป ให้ทำดังนี้
สร้างอินสแตนซ์
SurfaceView
รับอินสแตนซ์
avSyncHwId
จากTuner
สร้างอินสแตนซ์
AudioTrack
และMediaCodec
ด้วยอินสแตนซ์avSyncHwId
ที่สร้างในขั้นตอนที่ 2
ลำดับการเรียก API แสดงอยู่ในข้อมูลโค้ดต่อไปนี้
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);
ลักษณะการทำงานของการเล่นวิดีโอออนดีมานด์
เนื่องจากการเล่นวิดีโอออนดีมานด์ที่ผ่านการเชื่อมต่ออุโมงค์จะเชื่อมโยงกับการAudioTrack
เล่นโดยนัย ลักษณะการทำงานของการเล่นวิดีโอที่ผ่านการเชื่อมต่ออุโมงค์จึงอาจขึ้นอยู่กับลักษณะการทำงาน
ของการเล่นเสียง
ในอุปกรณ์ส่วนใหญ่ โดยค่าเริ่มต้นแล้ว ระบบจะไม่แสดงเฟรมวิดีโอจนกว่าจะเริ่มเล่นเสียง อย่างไรก็ตาม แอปอาจต้องแสดงผลเฟรมวิดีโอก่อน เริ่มเล่นเสียง เช่น เพื่อแสดงตำแหน่งวิดีโอปัจจุบันแก่ผู้ใช้ขณะกรอ
หากต้องการส่งสัญญาณว่าควรแสดงเฟรมวิดีโอแรกที่อยู่ในคิวทันทีที่ถอดรหัสแล้ว ให้ตั้งค่าพารามิเตอร์
PARAMETER_KEY_TUNNEL_PEEK
เป็น1
เมื่อมีการจัดลำดับเฟรมวิดีโอที่บีบอัดใหม่ในคิว (เช่น เมื่อมีB-frame ) หมายความว่าเฟรมวิดีโอแรกที่แสดงควรเป็น I-frame เสมอหากไม่ต้องการให้แสดงเฟรมวิดีโอแรกที่อยู่ในคิวจนกว่าการเล่นเสียงจะเริ่ม ให้ตั้งค่าพารามิเตอร์นี้เป็น
0
หากไม่ได้ตั้งค่าพารามิเตอร์นี้ OEM จะเป็นผู้กำหนดลักษณะการทำงานของอุปกรณ์
เมื่อไม่ได้ระบุข้อมูลเสียงให้กับ
AudioTrack
และบัฟเฟอร์ว่างเปล่า (เสียงขาดตอน) การเล่นวิดีโอจะหยุดชะงักจนกว่าจะมีการเขียนข้อมูลเสียงเพิ่มเติม เนื่องจากนาฬิกาเสียงไม่ทำงานอีกต่อไปในระหว่างการเล่น การหยุดชะงักที่แอปแก้ไขไม่ได้อาจปรากฏใน การประทับเวลาการนำเสนอเสียง เมื่อเกิดกรณีนี้ขึ้น OEM จะแก้ไขช่องว่างเชิงลบ โดยการหยุดเฟรมวิดีโอปัจจุบันชั่วคราว และแก้ไขช่องว่างเชิงบวกโดยการทิ้ง เฟรมวิดีโอหรือแทรกเฟรมเสียงที่ไม่มีเสียง (ขึ้นอยู่กับการติดตั้งใช้งานของ OEM ) ตำแหน่งเฟรม
AudioTimestamp
จะไม่เพิ่มขึ้นสำหรับ เฟรมเสียงเงียบที่แทรก
สำหรับผู้ผลิตอุปกรณ์
การกำหนดค่า
OEM ควรสร้างตัวถอดรหัสวิดีโอแยกต่างหากเพื่อรองรับการเล่นวิดีโอแบบ Tunnel
ตัวถอดรหัสนี้ควรโฆษณาว่าสามารถเล่นแบบ Tunnel ได้ในไฟล์ media_codecs.xml
<Feature name="tunneled-playback" required="true"/>
เมื่อกำหนดค่าอินสแตนซ์ MediaCodec
ที่มีการทำอุโมงค์ด้วยรหัสเซสชันเสียง อินสแตนซ์จะ
ค้นหา AudioFlinger
สำหรับรหัส HW_AV_SYNC
นี้
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);
}
ในระหว่างการค้นหานี้
AudioFlinger
จะดึงข้อมูลรหัส HW_AV_SYNC
จากอุปกรณ์เสียงหลักและเชื่อมโยงรหัสนี้กับรหัสเซสชันเสียง
ภายใน
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);
หากสร้างอินสแตนซ์ AudioTrack
แล้ว ระบบจะส่งรหัส HW_AV_SYNC
ไปยังสตรีมเอาต์พุตที่มีรหัสเซสชันเสียงเดียวกัน
หากยังไม่ได้สร้าง ระบบจะส่ง HW_AV_SYNC
ID ไปยังสตรีมเอาต์พุตในระหว่างการสร้างAudioTrack
โดยเธรดการเล่นจะดำเนินการดังนี้
mOutput->stream->common.set_parameters(&mOutput->stream->common, AUDIO_PARAMETER_STREAM_HW_AV_SYNC, hwAVSyncId);
ระบบจะส่งรหัส HW_AV_SYNC
ไม่ว่าจะตรงกับสตรีมเอาต์พุตเสียงหรือการกำหนดค่า Tuner
ไปยังคอมโพเนนต์ OMX หรือ Codec2 เพื่อให้โค้ด OEM เชื่อมโยงตัวแปลงรหัสกับสตรีมเอาต์พุตเสียงที่เกี่ยวข้องหรือสตรีมจูนเนอร์ได้
ในระหว่างการกำหนดค่าคอมโพเนนต์ คอมโพเนนต์ OMX หรือ Codec2 ควรแสดงแฮนเดิลแถบข้างที่ใช้เชื่อมโยงตัวแปลงรหัสกับเลเยอร์ Hardware Composer (HWC) ได้ เมื่อแอปเชื่อมโยง Surface กับ MediaCodec
ระบบจะส่งแฮนเดิลแถบข้างนี้ไปยัง HWC ผ่าน SurfaceFlinger
ซึ่งจะกำหนดค่าเลเยอร์เป็นเลเยอร์แถบข้าง
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 มีหน้าที่รับบัฟเฟอร์รูปภาพใหม่จากเอาต์พุตของตัวแปลงรหัสในเวลาที่เหมาะสม ไม่ว่าจะซิงค์กับสตรีมเอาต์พุตเสียงที่เกี่ยวข้องหรือนาฬิกาอ้างอิงของโปรแกรมจูนเนอร์ การคอมโพสิตบัฟเฟอร์กับเนื้อหาปัจจุบันของเลเยอร์อื่นๆ และแสดงรูปภาพที่ได้ ซึ่งจะเกิดขึ้น โดยไม่ขึ้นอยู่กับวงจรการเตรียมและการตั้งค่าปกติ การเรียกใช้ prepare และ set จะเกิดขึ้นเมื่อเลเยอร์อื่นๆ เปลี่ยนแปลง หรือเมื่อพร็อพเพอร์ตี้ของเลเยอร์แถบข้าง (เช่น ตำแหน่งหรือขนาด) เปลี่ยนแปลงเท่านั้น
OMX
คอมโพเนนต์ตัวถอดรหัสที่ส่งผ่านอุโมงค์ควรรองรับสิ่งต่อไปนี้
การตั้งค่าพารามิเตอร์
OMX.google.android.index.configureVideoTunnelMode
extended ซึ่งใช้โครงสร้างConfigureVideoTunnelModeParams
เพื่อส่ง ในรหัสHW_AV_SYNC
ที่เชื่อมโยงกับอุปกรณ์เอาต์พุตเสียงการกำหนดค่าพารามิเตอร์
OMX_IndexConfigAndroidTunnelPeek
ที่บอกให้ตัวแปลงรหัส แสดงผลหรือไม่แสดงผลเฟรมวิดีโอแรกที่ถอดรหัสแล้ว ไม่ว่าการเล่นเสียงจะเริ่มแล้วหรือไม่ก็ตามส่งเหตุการณ์
OMX_EventOnFirstTunnelFrameReady
เมื่อถอดรหัสเฟรมวิดีโอแรกที่ผ่านการอุโมงค์ และพร้อมที่จะแสดงผล
การติดตั้งใช้งาน AOSP จะกำหนดค่าโหมด Tunnel ใน
ACodec
ผ่าน
OMXNodeInstance
ดังที่แสดงในข้อมูลโค้ดต่อไปนี้
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;
หากคอมโพเนนต์รองรับการกำหนดค่านี้ คอมโพเนนต์ควรจัดสรรแฮนเดิลแถบข้าง
ให้กับตัวแปลงรหัสนี้และส่งกลับผ่านสมาชิก pSidebandWindow
เพื่อให้
HWC ระบุตัวแปลงรหัสที่เชื่อมโยงได้ หากคอมโพเนนต์ไม่
รองรับการกำหนดค่านี้ คอมโพเนนต์ควรตั้งค่า bTunneled
เป็น OMX_FALSE
ตัวแปลงรหัส 2
ใน Android 11 ขึ้นไป Codec2
รองรับการเล่นแบบ Tunnel คอมโพเนนต์ตัวถอดรหัส
ควรรองรับสิ่งต่อไปนี้
การกำหนดค่า
C2PortTunneledModeTuning
ซึ่งกำหนดค่าโหมดอุโมงค์และ ส่งผ่านในHW_AV_SYNC
ที่ดึงมาจากอุปกรณ์เอาต์พุตเสียงหรือ การกำหนดค่าจูนเนอร์การค้นหา
C2_PARAMKEY_OUTPUT_TUNNEL_HANDLE
เพื่อจัดสรรและเรียกข้อมูล แฮนเดิลแถบข้างสำหรับ HWCการจัดการ
C2_PARAMKEY_TUNNEL_HOLD_RENDER
เมื่อแนบไปกับC2Work
ซึ่ง สั่งให้ตัวแปลงรหัสถอดรหัสและส่งสัญญาณว่าดำเนินการเสร็จแล้ว แต่ไม่ให้แสดงผล บัฟเฟอร์เอาต์พุตจนกว่า 1) จะมีการสั่งให้ตัวแปลงรหัสแสดงผลในภายหลัง หรือ 2) การเล่นเสียงจะเริ่มขึ้นการจัดการ
C2_PARAMKEY_TUNNEL_START_RENDER
ซึ่งจะสั่งให้ตัวแปลงรหัส แสดงเฟรมที่ทำเครื่องหมายด้วยC2_PARAMKEY_TUNNEL_HOLD_RENDER
ทันที แม้ว่าการเล่นเสียงจะยังไม่เริ่มก็ตามปล่อยให้
debug.stagefright.ccodec_delayed_params
ไม่ได้กำหนดค่า (แนะนำ) หากกำหนดค่า ให้ตั้งเป็นfalse
การติดตั้งใช้งาน AOSP จะกำหนดค่าโหมดอุโมงค์ใน
CCodec
ผ่าน C2PortTunnelModeTuning
ดังที่แสดงในข้อมูลโค้ดต่อไปนี้
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;
}
หากคอมโพเนนต์รองรับการกำหนดค่านี้ คอมโพเนนต์ควรจัดสรรแฮนเดิลแถบข้าง
ให้กับตัวแปลงรหัสนี้และส่งกลับผ่าน C2PortTunnelHandlingTuning
เพื่อให้
HWC ระบุตัวแปลงรหัสที่เชื่อมโยงได้
HAL เสียง
สำหรับการเล่นวิดีโอแบบออนดีมานด์ HAL เสียงจะได้รับการนำเสนอเสียง การประทับเวลาแบบอินไลน์พร้อมกับข้อมูลเสียงในรูปแบบ Big-Endian ภายในส่วนหัวที่พบ ที่จุดเริ่มต้นของแต่ละบล็อกของข้อมูลเสียงที่แอปเขียน
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 แสดงผลเฟรมวิดีโอพร้อมกับเฟรมเสียงที่เกี่ยวข้อง Audio HAL ควรแยกวิเคราะห์ส่วนหัวของการซิงค์และใช้การประทับเวลาการนำเสนอเพื่อ ซิงค์นาฬิกาการเล่นใหม่กับการแสดงผลเสียง หากต้องการซิงค์อีกครั้งเมื่อเล่นเสียงที่บีบอัด HAL เสียงอาจต้องแยกวิเคราะห์ข้อมูลเมตาภายในข้อมูลเสียงที่บีบอัดเพื่อกำหนดระยะเวลาการเล่น
หยุดการสนับสนุนชั่วคราว
Android 5 หรือต่ำกว่าไม่รองรับการหยุดชั่วคราว คุณจะหยุดการเล่นที่ส่งผ่านอุโมงค์ชั่วคราวได้ก็ต่อเมื่อ A/V ไม่เพียงพอเท่านั้น แต่หากบัฟเฟอร์ภายในสำหรับวิดีโอมีขนาดใหญ่ (เช่น มีข้อมูล 1 วินาทีในคอมโพเนนต์ OMX) การหยุดชั่วคราวจะดูเหมือนไม่ตอบสนอง
ใน Android 5.1 ขึ้นไป AudioFlinger
รองรับการหยุดชั่วคราวและเล่นต่อสำหรับเอาต์พุตเสียงโดยตรง (แบบอุโมงค์) หาก HAL ใช้การหยุดชั่วคราวและกลับมาทำงานต่อ ระบบจะส่งต่อการหยุดชั่วคราว
และการกลับมาทำงานต่อไปยัง HAL
ลำดับการเรียกใช้ pause, flush, resume จะได้รับการพิจารณาโดยการเรียกใช้ HAL ในเธรดการเล่น (เช่นเดียวกับการออฟโหลด)
คำแนะนำในการใช้งาน
HAL เสียง
สำหรับ Android 11 สามารถใช้รหัสการซิงค์ HW จาก PCR หรือ STC สำหรับการซิงค์ A/V ได้ ดังนั้นระบบจึงรองรับสตรีมวิดีโอเท่านั้น
สำหรับ Android 10 หรือต่ำกว่า อุปกรณ์ที่รองรับการเล่นวิดีโอแบบ Tunnel ควรมี
โปรไฟล์สตรีมเอาต์พุตเสียงอย่างน้อย 1 รายการที่มีแฟล็ก FLAG_HW_AV_SYNC
และ
AUDIO_OUTPUT_FLAG_DIRECT
ในไฟล์ audio_policy.conf
ค่าสถานะเหล่านี้
ใช้เพื่อตั้งค่านาฬิกาของระบบจากนาฬิกาเสียง
OMX
ผู้ผลิตอุปกรณ์ควรมีคอมโพเนนต์ OMX แยกต่างหากสำหรับการเล่นวิดีโอแบบ Tunnel (ผู้ผลิตอาจมีคอมโพเนนต์ OMX เพิ่มเติมสำหรับการเล่นเสียงและวิดีโอประเภทอื่นๆ เช่น การเล่นที่ปลอดภัย) คอมโพเนนต์ที่ผ่านอุโมงค์ ควรมีลักษณะดังนี้
ระบุบัฟเฟอร์ 0 รายการ (
nBufferCountMin
,nBufferCountActual
) ในเอาต์พุต พอร์ตติดตั้งใช้งานส่วนขยาย
OMX.google.android.index.prepareForAdaptivePlayback setParameter
ระบุความสามารถในไฟล์
media_codecs.xml
และประกาศฟีเจอร์การเล่นแบบอุโมงค์ นอกจากนี้ ควรระบุข้อจำกัดเกี่ยวกับขนาดเฟรม การจัดแนว หรือบิตเรตด้วย ตัวอย่างแสดงอยู่ด้านล่าง<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>
หากใช้คอมโพเนนต์ OMX เดียวกันเพื่อรองรับการถอดรหัสแบบมีและไม่มีการเชื่อมต่อ ควรปล่อยให้ฟีเจอร์การเล่นแบบเชื่อมต่อเป็นแบบไม่บังคับ จากนั้นดีโคดเดอร์ทั้งแบบที่ใช้และไม่ใช้การเชื่อมต่อผ่านอุโมงค์จะมีข้อจำกัดด้านความสามารถเหมือนกัน ตัวอย่างแสดงด้านล่าง
<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>
คอมโพสเซอร์ฮาร์ดแวร์ (HWC)
เมื่อมีเลเยอร์ที่ส่งผ่านอุโมงค์ (เลเยอร์ที่มี HWC_SIDEBAND
compositionType
) บนจอแสดงผล sidebandStream
ของเลเยอร์จะเป็นแฮนเดิลแถบข้างที่คอมโพเนนต์วิดีโอ OMX จัดสรร
HWC จะซิงค์เฟรมวิดีโอที่ถอดรหัสแล้ว (จากคอมโพเนนต์ OMX ที่ส่งผ่านอุโมงค์) กับ
แทร็กเสียงที่เกี่ยวข้อง (ที่มี audio-hw-sync
ID) เมื่อเฟรมวิดีโอใหม่
กลายเป็นเฟรมปัจจุบัน HWC จะรวมเฟรมดังกล่าวกับเนื้อหาปัจจุบันของเลเยอร์ทั้งหมด
ที่ได้รับระหว่างการเรียกเตรียมหรือตั้งค่าครั้งล่าสุด แล้วแสดงรูปภาพที่ได้
การเรียกใช้ prepare หรือ set จะเกิดขึ้นเมื่อเลเยอร์อื่นๆ เปลี่ยนแปลง หรือเมื่อพร็อพเพอร์ตี้ของเลเยอร์แถบข้าง (เช่น ตำแหน่งหรือขนาด) เปลี่ยนแปลงเท่านั้น
รูปภาพต่อไปนี้แสดงถึงการทำงานของ HWC ร่วมกับตัวซิงโครไนซ์ฮาร์ดแวร์ (หรือเคอร์เนลหรือ ไดรเวอร์) เพื่อรวมเฟรมวิดีโอ (7b) กับองค์ประกอบล่าสุด (7a) สำหรับการแสดงผลในเวลาที่ถูกต้องตามเสียง (7c)
รูปที่ 2 ตัวซิงค์ฮาร์ดแวร์ HWC (หรือเคอร์เนลหรือไดรเวอร์)