การสร้างอุโมงค์มัลติมีเดียช่วยให้ข้อมูลวิดีโอที่บีบอัดผ่านเครื่องมือถอดรหัสวิดีโอฮาร์ดแวร์ไปยังจอแสดงผลได้โดยตรง โดยไม่ต้องประมวลผลโดยโค้ดของแอปหรือโค้ดเฟรมเวิร์กของ Android รหัสเฉพาะอุปกรณ์ด้านล่างสแต็ก Android จะระบุเฟรมวิดีโอที่ควรส่งไปยังจอแสดงผลและเวลาที่จะส่งเฟรมวิดีโอ โดยเปรียบเทียบการประทับเวลาการนำเสนอเฟรมวิดีโอกับนาฬิกาภายในประเภทใดประเภทหนึ่งต่อไปนี้
สำหรับการเล่นวิดีโอแบบออนดีมานด์ใน Android 5 ขึ้นไป นาฬิกา
AudioTrack
ที่ซิงค์กับการประทับเวลาการนำเสนอเสียงที่แอปส่งผ่านสําหรับการเล่นการออกอากาศสดใน Android 11 ขึ้นไป นาฬิกาอ้างอิงโปรแกรม (PCR) หรือนาฬิกาเวลาของระบบ (STC) ที่ขับเคลื่อนโดยจูนเนอร์
ฉากหลัง
การเล่นวิดีโอแบบดั้งเดิมใน Android จะแจ้งเตือนแอปเมื่อมีการถอดรหัสเฟรมวิดีโอที่บีบอัดแล้ว จากนั้นแอปจะปล่อยเฟรมวิดีโอที่ถอดรหัสไปยังจอแสดงผลเพื่อแสดงผลตามเวลาของนาฬิกาของระบบเดียวกันกับเฟรมเสียงที่เกี่ยวข้อง โดยดึงข้อมูลอินสแตนซ์AudioTimestamps
ที่ผ่านมาเพื่อคำนวณเวลาที่ถูกต้อง
เนื่องจากการเล่นวิดีโอ Tunnel จะข้ามโค้ดของแอปและช่วยลดจำนวนกระบวนการดำเนินการกับวิดีโอ จึงสามารถให้การแสดงผลวิดีโอที่มีประสิทธิภาพมากขึ้นได้โดยขึ้นอยู่กับการใช้งาน OEM นอกจากนี้ ยังให้ความถี่และการซิงค์ของวิดีโอที่แม่นยำมากขึ้นกับนาฬิกา (PRC, STC หรือเสียง) เพื่อหลีกเลี่ยงปัญหาที่อาจเกิดจากความคลาดเคลื่อนระหว่างเวลาที่คำขอของ Android ในการแสดงภาพวิดีโอกับช่วงเวลาของ vsync ฮาร์ดแวร์ที่แท้จริง อย่างไรก็ตาม การส่งผ่านนี้ยังอาจลดการรองรับเอฟเฟกต์ GPU เช่น การเบลอ หรือมุมมนในหน้าต่างภาพซ้อนภาพ (PiP) เนื่องจากบัฟเฟอร์จะข้ามสแต็กกราฟิก Android
แผนภาพต่อไปนี้แสดงวิธีที่ Tunnel ทำให้กระบวนการเล่นวิดีโอง่ายขึ้น
รูปที่ 1 การเปรียบเทียบกระบวนการเล่นวิดีโอแบบดั้งเดิมและ Tunnel
สำหรับนักพัฒนาแอป
เนื่องจากนักพัฒนาแอปส่วนใหญ่ผสานรวมกับไลบรารีสําหรับการใช้งานการเล่น ในกรณีส่วนใหญ่ การใช้งานจึงจําเป็นต้องกำหนดค่าไลบรารีดังกล่าวใหม่สําหรับการเล่นแบบใช้อุโมงค์เท่านั้น โปรดทำตามวิธีการต่อไปนี้เพื่อใช้โปรแกรมเล่นวิดีโอแบบ Tunnel ระดับต่ำ
สำหรับการเล่นวิดีโอแบบออนดีมานด์ใน 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 ในไฟล์ 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
ระบบจะส่งรหัส HW_AV_SYNC
ไปยังสตรีมเอาต์พุตระหว่างการสร้าง AudioTrack
การอ่านจะทำดังนี้
mOutput->stream->common.set_parameters(&mOutput->stream->common, AUDIO_PARAMETER_STREAM_HW_AV_SYNC, hwAVSyncId);
ระบบจะส่งรหัส HW_AV_SYNC
ไปยังคอมโพเนนต์ OMX หรือ Codec2 ไม่ว่ารหัสจะสอดคล้องกับสตรีมเอาต์พุตเสียงหรือการกำหนดค่า Tuner
เพื่อให้โค้ด OEM เชื่อมโยงตัวแปลงรหัสกับสตรีมเอาต์พุตเสียงหรือสตรีมจูนเนอร์ที่เกี่ยวข้องได้
ในระหว่างการกําหนดค่าคอมโพเนนต์ คอมโพเนนต์ OMX หรือ Codec2 ควรแสดงผลแฮนเดิลย่านความถี่ที่สามารถใช้เชื่อมโยงตัวแปลงรหัสกับเลเยอร์คอมโพเซอร์ฮาร์ดแวร์ (HWC) เมื่อแอปเชื่อมโยงพื้นผิวกับ 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 มีหน้าที่รับบัฟเฟอร์รูปภาพใหม่จากเอาต์พุตของตัวแปลงรหัสในเวลาที่เหมาะสม ไม่ว่าจะเป็นการซิงค์กับสตรีมเอาต์พุตเสียงที่เกี่ยวข้องหรือนาฬิกาอ้างอิงของโปรแกรมจูนเนอร์ รวมบัฟเฟอร์เข้ากับเนื้อหาปัจจุบันของเลเยอร์อื่นๆ และแสดงรูปภาพที่เป็นผลลัพธ์ ซึ่งจะเกิดขึ้นโดยไม่เกี่ยวข้องกับรอบการเตรียมและการตั้งค่าปกติ การเรียกใช้เพื่อเตรียมและตั้งค่าจะเกิดขึ้นเฉพาะเมื่อเลเยอร์อื่นๆ มีการเปลี่ยนแปลง หรือเมื่อคุณสมบัติของเลเยอร์ไซด์แบนด์ (เช่น ตำแหน่งหรือขนาด) มีการเปลี่ยนแปลง
OMX
คอมโพเนนต์ตัวถอดรหัส Tunnel ควรรองรับรายการต่อไปนี้
การตั้งค่าพารามิเตอร์ขยาย
OMX.google.android.index.configureVideoTunnelMode
ซึ่งใช้โครงสร้างConfigureVideoTunnelModeParams
เพื่อส่งผ่านรหัสHW_AV_SYNC
ที่เชื่อมโยงกับอุปกรณ์เอาต์พุตเสียงการกำหนดค่าพารามิเตอร์
OMX_IndexConfigAndroidTunnelPeek
ที่บอกตัวแปลงรหัสให้แสดงผลหรือไม่แสดงผลเฟรมวิดีโอที่ถอดรหัสครั้งแรก โดยไม่คำนึงว่าจะเล่นเสียงไปแล้วหรือไม่กำลังส่งเหตุการณ์
OMX_EventOnFirstTunnelFrameReady
เมื่อถอดรหัสเฟรมวิดีโอ Tunnel แรกและพร้อมที่จะแสดงผล
การใช้งาน 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
รองรับการเล่นแบบใช้อุโมงค์ คอมโพเนนต์โปรแกรมถอดรหัสควรรองรับสิ่งต่อไปนี้
การกำหนดค่า
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 จะกำหนดค่าโหมด Tunnel ใน 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 แสดงผลเฟรมวิดีโอให้ตรงกับเฟรมเสียงที่สอดคล้องกัน HAL ของเสียงควรแยกวิเคราะห์ส่วนหัวการซิงค์และใช้การประทับเวลาการนำเสนอเพื่อซิงค์นาฬิกาการเล่นกับการแสดงผลเสียงอีกครั้ง หากต้องการซิงค์อีกครั้งเมื่อเล่นเสียงที่บีบอัด เสียง HAL ของเสียงอาจต้องแยกวิเคราะห์ข้อมูลเมตาภายในข้อมูลเสียงที่บีบอัดเพื่อระบุระยะเวลาการเล่น
หยุดการสนับสนุนชั่วคราว
Android 5 หรือต่ำกว่าจะไม่รวมการสนับสนุนการหยุดชั่วคราว คุณจะหยุดเล่นวิดีโอที่ส่งผ่านอุโมงค์ชั่วคราวได้ก็ต่อเมื่อไม่มีพื้นที่เก็บข้อมูล A/V เพียงพอเท่านั้น แต่หากบัฟเฟอร์ภายในสำหรับวิดีโอมีขนาดใหญ่ (เช่น มีข้อมูล 1 วินาทีในคอมโพเนนต์ OMX) ระบบจะทําให้ดูเหมือนว่าหยุดชั่วคราวไม่ตอบสนอง
ใน Android 5.1 ขึ้นไป AudioFlinger
จะรองรับการหยุดชั่วคราวและเล่นต่อสำหรับเอาต์พุตเสียงโดยตรง (ที่มีการส่งผ่านอุโมงค์) หาก HAL ใช้การหยุดชั่วคราวและกลับมาทำงานต่อ ระบบจะส่งต่อการหยุดชั่วคราวและการกลับมาทำงานต่อของแทร็กไปยัง HAL
ระบบจะดำเนินการตามลำดับการเรียกใช้การหยุดชั่วคราว ล้างข้อมูล และเล่นต่อโดยเรียกใช้ HAL ในเธรดการเล่น (เหมือนกับการโอน)
คำแนะนำการติดตั้งใช้งาน
HAL เสียง
สำหรับ Android 11 จะใช้รหัสการซิงค์ HW จาก PCR หรือ STC สำหรับการซิงค์ A/V ได้ ดังนั้นจึงรองรับสตรีมวิดีโอเท่านั้น
สำหรับ Android 10 หรือต่ำกว่า อุปกรณ์ที่รองรับการเล่นวิดีโอ Tunnel ควรมีโปรไฟล์สตรีมเอาต์พุตเสียงอย่างน้อย 1 โปรไฟล์ที่มี Flag FLAG_HW_AV_SYNC
และ AUDIO_OUTPUT_FLAG_DIRECT
ในไฟล์ audio_policy.conf
ค่าสถานะเหล่านี้ใช้ในการตั้งค่านาฬิการะบบจากนาฬิกาเสียง
OMX
ผู้ผลิตอุปกรณ์ควรมีคอมโพเนนต์ OMX แยกต่างหากสำหรับการเล่นวิดีโอแบบ Tunnel (ผู้ผลิตอาจมีคอมโพเนนต์ OMX เพิ่มเติมสำหรับการเล่นเสียงและวิดีโอประเภทอื่นๆ เช่น การเล่นที่ปลอดภัย) คอมโพเนนต์ Tunnel ควรมีลักษณะดังนี้
ระบุบัฟเฟอร์ 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 เดียวกันเพื่อรองรับการถอดรหัสแบบ Tunneled และแบบไม่ใช้ Tunneled คุณควรตั้งค่าฟีเจอร์การเล่นแบบ Tunneled ไว้ว่าไม่จำเป็น ทั้งตัวถอดรหัสแบบใช้อุโมงค์และแบบไม่ใช้อุโมงค์จึงมีข้อจำกัดด้านความสามารถเหมือนกัน ตัวอย่างแสดงอยู่ด้านล่าง
<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
) เมื่อเฟรมวิดีโอใหม่กลายเป็นเฟรมปัจจุบัน HWC จะคอมโพสเฟรมนั้นกับเนื้อหาปัจจุบันของเลเยอร์ทั้งหมดที่ได้รับระหว่างการเรียกใช้เตรียมหรือตั้งค่าครั้งล่าสุด และแสดงภาพที่ได้
การเรียกใช้เตรียมหรือตั้งค่าจะเกิดขึ้นเฉพาะเมื่อเลเยอร์อื่นๆ เปลี่ยนแปลง หรือเมื่อคุณสมบัติของเลเยอร์แถบด้านข้าง (เช่น ตําแหน่งหรือขนาด) เปลี่ยนแปลง
ภาพต่อไปนี้แสดง HWC ที่ทำงานกับเครื่องมือซิงโครไนซ์ฮาร์ดแวร์ (หรือเคอร์เนลหรือไดรเวอร์) เพื่อรวมเฟรมวิดีโอ (7b) เข้ากับองค์ประกอบล่าสุด (7a) สำหรับการแสดงตามเวลาที่ถูกต้องตามเสียง (7c)
รูปที่ 2 ตัวซิงค์ฮาร์ดแวร์ (หรือเคอร์เนลหรือไดรเวอร์) HWC