ใน Exterior View System (EVS) รุ่นก่อนหน้า
IEvsCameraStream
อินเทอร์เฟซที่กำหนดเมธอด Callback เดียวเพื่อส่งวิดีโอที่บันทึกไว้
เฟรมเท่านั้น แม้ว่าการใช้บริการ EVS ของลูกค้าจะง่ายขึ้น แต่
ทำให้ลูกค้าระบุเหตุการณ์สตรีมได้ยาก ดังนั้น
เพื่อจัดการอย่างเหมาะสม เพื่อปรับปรุงประสบการณ์การพัฒนา EVS ตอนนี้ AOSP มี
Callback เพิ่มเติมเพื่อแสดงกิจกรรมสตรีมมิง
package android.hardware.automotive.evs@1.1;
import @1.0::IEvsCameraStream;
/**
* Implemented on client side to receive asynchronous video frame deliveries.
*/
interface IEvsCameraStream extends @1.0::IEvsCameraStream {
/**
* Receives calls from the HAL each time a video frame is ready for inspection.
* Buffer handles received by this method must be returned via calls to
* IEvsCamera::doneWithFrame_1_1(). When the video stream is stopped via a call
* to IEvsCamera::stopVideoStream(), this callback may continue to happen for
* some time as the pipeline drains. Each frame must still be returned.
* When the last frame in the stream has been delivered, STREAM_STOPPED
* event must be delivered. No further frame deliveries may happen
* thereafter.
*
* @param buffer a buffer descriptor of a delivered image frame.
*/
oneway deliverFrame_1_1(BufferDesc buffer);
/**
* Receives calls from the HAL each time an event happens.
*
* @param event EVS event with possible event information.
*/
oneway notify(EvsEvent event);
};
วิธีนี้จะแสดง EvsEventDesc
ซึ่งประกอบด้วย 3 ช่อง
- ประเภทของกิจกรรม
- สตริงสำหรับระบุต้นทางของเหตุการณ์
- ข้อมูลคำแบบ 4x 32 บิตเพื่อให้มีข้อมูลเหตุการณ์ที่เป็นไปได้
/**
* Structure that describes informative events occurred during EVS is streaming
*/
struct EvsEvent {
/**
* Type of an informative event
*/
EvsEventType aType;
/**
* Device identifier
*/
string deviceId;
/**
* Possible additional information
*/
uint32_t[4] payload;
};
และเพื่อหลีกเลี่ยงความแตกต่างของรายละเอียดบัฟเฟอร์ของกราฟิกระหว่าง EVS
และคอมโพเนนต์กราฟิกอื่นๆ ของ Android ได้กำหนด BufferDesc
เป็น
ใช้ HardwareBuffer
ที่นำเข้าจากอินเทอร์เฟซ android.hardware.graphics.common@1.2
HardwareBuffer
มี HardwareBufferDescription
ซึ่งเป็น
HIDL ของ Android NDK
AHardwareBuffer_Desc
พร้อมด้วยแฮนเดิลบัฟเฟอร์
/**
* HIDL counterpart of AHardwareBuffer_Desc.
*
* An AHardwareBuffer_Desc object can be converted to and from a
* HardwareBufferDescription object by memcpy().
*
* @sa +ndk libnativewindow#AHardwareBuffer_Desc.
*/
typedef uint32_t[10] HardwareBufferDescription;
/**
* HIDL counterpart of AHardwareBuffer.
*
* AHardwareBuffer_createFromHandle() can be used to convert a HardwareBuffer
* object to an AHardwareBuffer object.
*
* Conversely, AHardwareBuffer_getNativeHandle() can be used to extract a native
* handle from an AHardwareBuffer object. Paired with AHardwareBuffer_Desc,
* AHardwareBuffer_getNativeHandle() can be used to convert between
* HardwareBuffer and AHardwareBuffer.
*
* @sa +ndk libnativewindow#AHardwareBuffer".
*/
struct HardwareBuffer {
HardwareBufferDescription description;
handle nativeHandle;
}
/**
* Structure representing an image buffer through our APIs
*
* In addition to the handle to the graphics memory, need to retain
* the properties of the buffer for easy reference and reconstruction of
* an ANativeWindowBuffer object on the remote side of API calls.
* Not least because OpenGL expect an ANativeWindowBuffer* for us as a
* texture via eglCreateImageKHR().
*/
struct BufferDesc {
/**
* HIDL counterpart of AHardwareBuffer_Desc. Please see
* hardware/interfaces/graphics/common/1.2/types.hal for more details.
*/
HardwareBuffer buffer;
/**
* The size of a pixel in the units of bytes
*/
uint32_t pixelSize;
/**
* Opaque value from driver
*/
uint32_t bufferId;
/**
* Unique identifier of the physical camera device that produces this buffer.
*/
string deviceId;
/**
* Time that this buffer is being filled
*/
int64_t timestamp;
/**
* Frame metadata. This is opaque to EVS manager
*/
vec<uint8_t> metadata
};
หมายเหตุ: HardwareBufferDescription
ให้คำนิยามว่าเป็น
อาร์เรย์ของคำ 32 บิต 10 คำ คุณอาจต้องแคสต์เป็นประเภทAHardwareBuffer_Desc
แล้วใส่เนื้อหาลงไป
EvsEventDesc
เป็นโครงสร้างของ enum EvsEventType
ซึ่งแสดงเหตุการณ์สตรีมมิงหลายรายการ และเพย์โหลดคำแบบ 32 บิต ซึ่ง
สามารถให้ข้อมูลเพิ่มเติมที่เป็นไปได้ ตัวอย่างเช่น นักพัฒนาซอฟต์แวร์
วางรหัสข้อผิดพลาดสำหรับเหตุการณ์ที่มีข้อผิดพลาดในสตรีมมิงได้
/**
* Types of informative streaming events
*/
enum EvsEventType : uint32_t {
/**
* Video stream is started
*/
STREAM_STARTED = 0,
/**
* Video stream is stopped
*/
STREAM_STOPPED,
/**
* Video frame is dropped
*/
FRAME_DROPPED,
/**
* Timeout happens
*/
TIMEOUT,
/**
* Camera parameter is changed; payload contains a changed parameter ID and
* its value
*/
PARAMETER_CHANGED,
/**
* Master role has become available
*/
MASTER_RELEASED,
};
การนำส่งเฟรม
มี BufferDesc
ใหม่ IEvsCameraStream
ด้วย
แนะนำเมธอด Callback ใหม่เพื่อรับเฟรมและเหตุการณ์สตรีมมิง
จากการติดตั้งใช้งานบริการ
/**
* Implemented on client side to receive asynchronous streaming event deliveries.
*/
interface IEvsCameraStream extends @1.0::IEvsCameraStream {
/**
* Receives calls from the HAL each time video frames are ready for inspection.
* Buffer handles received by this method must be returned via calls to
* IEvsCamera::doneWithFrame_1_1(). When the video stream is stopped via a call
* to IEvsCamera::stopVideoStream(), this callback may continue to happen for
* some time as the pipeline drains. Each frame must still be returned.
* When the last frame in the stream has been delivered, STREAM_STOPPED
* event must be delivered. No further frame deliveries may happen
* thereafter.
*
* A camera device delivers the same number of frames as number of
* backing physical camera devices; it means, a physical camera device
* sends always a single frame and a logical camera device sends multiple
* frames as many as the number of backing physical camera devices.
*
* @param buffer Buffer descriptors of delivered image frames.
*/
oneway deliverFrame_1_1(vec<BufferDesc> buffer);
/**
* Receives calls from the HAL each time an event happens.
*
* @param event EVS event with possible event information.
*/
oneway notify(EvsEventDesc event);
};
เวอร์ชันใหม่ของ Method Callback ของเฟรมออกแบบมาเพื่อแสดง ตัวบ่งชี้บัฟเฟอร์หลายรายการ ดังนั้น การใช้งานกล้อง EVS จึงสามารถส่งต่อ หลายเฟรมตามการเรียกครั้งเดียว หากโค้ดจัดการแหล่งที่มาหลายแหล่ง
นอกจากนี้ โปรโตคอลก่อนหน้านี้ที่ใช้แจ้งเตือนเกี่ยวกับช่วงท้ายของสตรีม ซึ่งก็คือ
การส่งเฟรม Null เลิกใช้งานแล้วและแทนที่ด้วย STREAM_STOPPED
กิจกรรม
รูปที่ 1 แผนภาพลำดับการแจ้งเตือนเหตุการณ์
ใช้เหตุการณ์และกลไกการแจ้งเตือนเฟรม
ระบุเวอร์ชันของ IEvscameraStream ที่ไคลเอ็นต์นำไปใช้
บริการสามารถระบุเวอร์ชันของอินเทอร์เฟซ IEvscameraStream ขาเข้า ที่ลูกค้านำมาใช้งานด้วยการพยายามลดขนาดข้อมูลลง
using IEvsCameraStream_1_0 =
::android::hardware::automotive::evs::V1_0::IEvsCameraStream;
using IEvsCameraStream_1_1 =
::android::hardware::automotive::evs::V1_1::IEvsCameraStream;
Return<EvsResult> EvsV4lCamera::startVideoStream(
const sp<IEvsCameraStream_1_0>& stream) {
IEvsCameraStream_1_0 aStream = stream;
// Try to downcast. This succeeds if the client implements
// IEvsCameraStream v1.1.
IEvsCameraStream_1_1 aStream_1_1 =
IEvsCameraStream_1_1::castFrom(aStream).withDefault(nullptr);
if (aStream_1_1 == nullptr) {
ALOGI("Start a stream for v1.0 client.");
} else {
ALOGI("Start a stream for v1.1 client.");
}
// Start a video stream
...
}
notify() Callback
EvsEvent
ผ่านการติดต่อกลับของ notify()
และ
ไคลเอ็นต์จะระบุประเภทของตนตาม Disriminator ตามที่ปรากฏด้านล่าง
Return<void> StreamHandler::notify(const EvsEvent& event) {
ALOGD("Received an event id: %u", event.aType);
// Handle each received event.
switch(event.aType) {
case EvsEventType::ERROR:
// Do something to handle an error
...
break;
[More cases]
}
return Void();
}
ใช้ BufferDesc
AHardwareBuffer_Desc
เป็นประเภทข้อมูลของ Android NDK ที่แสดงถึงบัฟเฟอร์ของฮาร์ดแวร์เนทีฟที่ผูกกับ
EGL/OpenGL และ Vulkan Primes ซึ่งมีข้อมูลเมตาส่วนใหญ่ของบัฟเฟอร์จากก่อนหน้านี้
ด้วยเหตุนี้ EVS BufferDesc จึงแทนที่ด้วยคําจํากัดความ BufferDesc ใหม่ อย่างไรก็ตาม
คืออาร์เรย์ในอินเทอร์เฟซ HIDL คุณจะจัดทำดัชนีตัวแปรสมาชิกโดยตรงไม่ได้
แต่คุณสามารถแคสต์อาร์เรย์เป็นประเภท AHardwareBuffer_Desc
แทนได้ ดังนี้
BufferDesc bufDesc = {};
AHardwareBuffer_Desc* pDesc =
reinterpret_cast<AHardwareBuffer_Desc *>(&bufDesc.buffer.description);
pDesc->width = mVideo.getWidth();
pDesc->height = mVideo.getHeight();
pDesc->layers = 1;
pDesc->format = mFormat;
pDesc->usage = mUsage;
pDesc->stride = mStride;
bufDesc_1_1.buffer.nativeHandle = mBuffers[idx].handle;
bufDesc_1_1.bufferId = idx;