25 #include <stdatomic.h>
29 #include <camera/NdkCameraDevice.h>
30 #include <camera/NdkCameraManager.h>
31 #include <media/NdkImage.h>
32 #include <media/NdkImageReader.h>
50 #define IMAGE_FORMAT_ANDROID AIMAGE_FORMAT_YUV_420_888
52 #define MAX_BUF_COUNT 2
53 #define VIDEO_STREAM_INDEX 0
54 #define VIDEO_TIMEBASE_ANDROID 1000000000
56 #define RETURN_CASE(x) case x: return AV_STRINGIFY(x);
57 #define RETURN_DEFAULT(x) default: return AV_STRINGIFY(x);
154 return "ERROR_CAMERA_UNKNOWN";
164 ACameraDevice_getId(device));
180 ACameraIdList *camera_ids;
182 ret = ACameraManager_getCameraIdList(ctx->
camera_mgr, &camera_ids);
183 if (ret != ACAMERA_OK) {
201 ACameraManager_deleteCameraIdList(camera_ids);
203 ret = ACameraManager_getCameraCharacteristics(ctx->
camera_mgr,
205 if (ret != ACAMERA_OK) {
206 av_log(avctx,
AV_LOG_ERROR,
"Failed to get metadata for camera with id %s, error: %s.\n",
217 if (ret != ACAMERA_OK) {
229 ACameraMetadata_const_entry lens_facing;
230 ACameraMetadata_const_entry sensor_orientation;
233 ACAMERA_LENS_FACING, &lens_facing);
235 ACAMERA_SENSOR_ORIENTATION, &sensor_orientation);
244 ACameraMetadata_const_entry available_configs;
248 ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
251 for (
int i = 0; i < available_configs.count; i++) {
252 int32_t input = available_configs.data.i32[i * 4 + 3];
274 if (!found || ctx->
width == 0 || ctx->
height == 0) {
275 ctx->
width = available_configs.data.i32[1];
276 ctx->
height = available_configs.data.i32[2];
279 "Requested video_size %dx%d not available, falling back to %dx%d\n",
289 ACameraMetadata_const_entry available_framerates;
291 int current_best_match = -1;
295 ACAMERA_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
296 &available_framerates);
298 for (
int i = 0; i < available_framerates.count; i++) {
299 int32_t min = available_framerates.data.i32[i * 2 + 0];
300 int32_t max = available_framerates.data.i32[i * 2 + 1];
302 if (requested_framerate == max) {
308 }
else if (current_best_match >= 0) {
309 int32_t current_best_match_min = available_framerates.data.i32[current_best_match * 2 + 0];
310 if (min > current_best_match_min) {
311 current_best_match = i;
314 current_best_match = i;
320 if (current_best_match >= 0) {
321 ctx->
framerate_range[0] = available_framerates.data.i32[current_best_match * 2 + 0];
322 ctx->
framerate_range[1] = available_framerates.data.i32[current_best_match * 2 + 1];
330 "Requested framerate %d not available, falling back to min: %d and max: %d fps\n",
342 int plane_data_length[2];
344 for (
int i = 0; i < 2; i++) {
345 AImage_getPlanePixelStride(image, i + 1, &image_pixelstrides[i]);
346 AImage_getPlaneData(image, i + 1, &image_plane_data[i], &plane_data_length[i]);
349 if (image_pixelstrides[0] != image_pixelstrides[1]) {
351 "Pixel strides of U and V plane should have been the same.\n");
355 switch (image_pixelstrides[0]) {
360 if (image_plane_data[0] < image_plane_data[1]) {
368 "Unknown pixel stride %d of U and V plane, cannot determine camera image format.\n",
369 image_pixelstrides[0]);
380 media_status_t media_status;
384 int64_t image_timestamp;
387 int plane_data_length[4];
390 int pkt_buffer_size = 0;
392 media_status = AImageReader_acquireLatestImage(reader, &image);
393 if (media_status != AMEDIA_OK) {
394 if (media_status == AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE) {
396 "An image reader frame was discarded");
399 "Failed to acquire latest image from image reader, error: %s.\n",
416 "Could not get image format of camera.\n");
424 AImage_getTimestamp(image, &image_timestamp);
426 AImage_getPlaneRowStride(image, 0, &image_linestrides[0]);
427 AImage_getPlaneData(image, 0, &image_plane_data[0], &plane_data_length[0]);
431 AImage_getPlaneRowStride(image, 1, &image_linestrides[1]);
432 AImage_getPlaneData(image, 1, &image_plane_data[1], &plane_data_length[1]);
433 AImage_getPlaneRowStride(image, 2, &image_linestrides[2]);
434 AImage_getPlaneData(image, 2, &image_plane_data[2], &plane_data_length[2]);
437 AImage_getPlaneRowStride(image, 1, &image_linestrides[1]);
438 AImage_getPlaneData(image, 1, &image_plane_data[1], &plane_data_length[1]);
441 AImage_getPlaneRowStride(image, 2, &image_linestrides[1]);
442 AImage_getPlaneData(image, 2, &image_plane_data[1], &plane_data_length[1]);
453 "Failed to create new av packet, error: %s.\n",
av_err2str(ret));
458 pkt.
pts = image_timestamp;
460 (
const uint8_t *
const *) image_plane_data,
470 "Error while processing new image, error: %s.\n",
av_err2str(ret));
475 "Input queue was full, dropping frame, consider raising the input_queue_size option (current value: %d)\n",
478 if (pkt_buffer_size) {
483 AImage_delete(image);
495 if (ret != AMEDIA_OK) {
505 if (ret != AMEDIA_OK) {
507 "Failed to set image listener on image reader, error: %s.\n",
513 if (ret != AMEDIA_OK) {
515 "Could not get image reader window, error: %s.\n",
544 if (ret != ACAMERA_OK) {
546 "Failed to create capture session output container, error: %s.\n",
554 if (ret != ACAMERA_OK) {
556 "Failed to create capture session container, error: %s.\n",
563 if (ret != ACAMERA_OK) {
565 "Failed to add output to output container, error: %s.\n",
571 if (ret != ACAMERA_OK) {
573 "Failed to create camera output target, error: %s.\n",
579 if (ret != ACAMERA_OK) {
581 "Failed to create capture request, error: %s.\n",
586 ret = ACaptureRequest_setEntry_i32(ctx->
capture_request, ACAMERA_CONTROL_AE_TARGET_FPS_RANGE,
588 if (ret != ACAMERA_OK) {
590 "Failed to set target fps range in capture request, error: %s.\n",
596 if (ret != ACAMERA_OK) {
598 "Failed to add capture request capture request, error: %s.\n",
610 if (ret != ACAMERA_OK) {
612 "Failed to create capture session, error: %s.\n",
618 if (ret != ACAMERA_OK) {
620 "Failed to set repeating request on capture session, error: %s.\n",
648 if (ctx->
lens_facing == ACAMERA_LENS_FACING_FRONT) {
659 memcpy(side_data, display_matrix,
sizeof(display_matrix));
783 "Failed to allocate input queue, error: %s.\n",
av_err2str(ret));
844 #define OFFSET(x) offsetof(AndroidCameraCtx, x)
845 #define DEC AV_OPT_FLAG_DECODING_PARAM
849 {
"camera_index",
"set index of camera to use",
OFFSET(camera_index),
AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX,
DEC },
850 {
"input_queue_size",
"set maximum number of frames to buffer",
OFFSET(input_queue_size),
AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX,
DEC },
863 .
name =
"android_camera",
870 .priv_class = &android_camera_class,
const char const char void * val
static void capture_session_ready(void *context, ACameraCaptureSession *session)
static const char * format[]
static void capture_session_active(void *context, ACameraCaptureSession *session)
#define atomic_store(object, desired)
void av_thread_message_queue_set_err_recv(AVThreadMessageQueue *mq, int err)
Set the receiving error code.
int av_image_copy_to_buffer(uint8_t *dst, int dst_size, const uint8_t *const src_data[4], const int src_linesize[4], enum AVPixelFormat pix_fmt, int width, int height, int align)
Copy image data from an image into a buffer.
ACaptureSessionOutput * capture_session_output
#define AV_LOG_WARNING
Something somehow does not look correct.
#define LIBAVUTIL_VERSION_INT
#define IMAGE_FORMAT_ANDROID
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
const char * av_default_item_name(void *ptr)
Return the context name.
static const char * media_status_string(media_status_t val)
#define VIDEO_STREAM_INDEX
ANativeWindow * image_reader_window
static int wait_for_image_format(AVFormatContext *avctx)
This struct describes the properties of an encoded stream.
void av_display_matrix_flip(int32_t matrix[9], int hflip, int vflip)
Flip the input matrix horizontally and/or vertically.
void av_display_rotation_set(int32_t matrix[9], double angle)
Initialize a transformation matrix describing a pure counterclockwise rotation by the specified angle...
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
static int add_video_stream(AVFormatContext *avctx)
int av_thread_message_queue_recv(AVThreadMessageQueue *mq, void *msg, unsigned flags)
Receive a message from the queue.
static const AVClass android_camera_class
static int android_camera_read_close(AVFormatContext *avctx)
ACaptureSessionOutputContainer * capture_session_output_container
This side data contains a 3x3 transformation matrix describing an affine transformation that needs to...
int av_thread_message_queue_send(AVThreadMessageQueue *mq, void *msg, unsigned flags)
Send a message on the queue.
int id
Format-specific stream ID.
static const char * camera_status_string(camera_status_t val)
#define VIDEO_TIMEBASE_ANDROID
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
ACaptureRequest * capture_request
int flags
Flags modifying the (de)muxer behaviour.
static double av_q2d(AVRational a)
Convert an AVRational to a double.
#define AVERROR_EOF
End of file.
int32_t framerate_range[2]
static av_cold int read_close(AVFormatContext *ctx)
#define RETURN_DEFAULT(x)
static void camera_dev_error(void *context, ACameraDevice *device, int error)
static int android_camera_read_header(AVFormatContext *avctx)
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
AVThreadMessageQueue * input_queue
int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align)
Return the size in bytes of the amount of data required to store an image with the given parameters...
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
#define atomic_load(object)
static void capture_session_closed(void *context, ACameraCaptureSession *session)
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
enum AVMediaType codec_type
General type of the encoded data.
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
AVInputFormat ff_android_camera_demuxer
AVRational avg_frame_rate
Average framerate.
static int create_image_reader(AVFormatContext *avctx)
ACameraCaptureSession * capture_session
as above, but U and V bytes are swapped
ACameraDevice_StateCallbacks camera_state_callbacks
static void get_sensor_orientation(AVFormatContext *avctx)
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
ACameraManager * camera_mgr
int32_t sensor_orientation
uint8_t * av_stream_new_side_data(AVStream *stream, enum AVPacketSideDataType type, int size)
Allocate new information from stream.
static void error(const char *err)
static int read_header(FFV1Context *f)
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
ACameraMetadata * camera_metadata
#define AV_LOG_INFO
Standard information.
char * av_strdup(const char *s)
Duplicate a string.
static int open_camera(AVFormatContext *avctx)
void av_thread_message_queue_set_err_send(AVThreadMessageQueue *mq, int err)
Set the sending error code.
static void match_video_size(AVFormatContext *avctx)
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Perform non-blocking operation.
static int add_display_matrix(AVFormatContext *avctx, AVStream *st)
Describe the class of an AVClass context structure.
static const AVOption options[]
static int create_capture_session(AVFormatContext *avctx)
Rational number (pair of numerator and denominator).
int av_thread_message_queue_alloc(AVThreadMessageQueue **mq, unsigned nelem, unsigned elsize)
Allocate a new message queue.
offset must point to AVRational
ACameraOutputTarget * camera_output_target
AImageReader_ImageListener image_listener
offset must point to two consecutive integers
Libavdevice version macros.
void av_thread_message_queue_free(AVThreadMessageQueue **mq)
Free a message queue.
ACameraCaptureSession_stateCallbacks capture_session_state_callbacks
static void match_framerate(AVFormatContext *avctx)
static const char * error_state_callback_string(int val)
static int android_camera_read_packet(AVFormatContext *avctx, AVPacket *pkt)
ACameraDevice * camera_dev
static void image_available(void *context, AImageReader *reader)
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
static void camera_dev_disconnected(void *context, ACameraDevice *device)
void * priv_data
Format private data.
atomic_int got_image_format
#define atomic_init(obj, value)
AImageReader * image_reader
AVCodecParameters * codecpar
Codec parameters associated with this stream.
AVRational r_frame_rate
Real base framerate of the stream.
#define AVERROR_EXTERNAL
Generic error in an external library.
This structure stores compressed data.
static int get_image_format(AVFormatContext *avctx, AImage *image)
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...