FFmpeg
Loading...
Searching...
No Matches
android_camera.c
Go to the documentation of this file.
1/*
2 * Android camera input device
3 *
4 * Copyright (C) 2017 Felix Matouschek
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include <errno.h>
24#include <pthread.h>
25#include <stdatomic.h>
26#include <stdbool.h>
27#include <stdint.h>
28#include <unistd.h>
29
30#include <camera/NdkCameraDevice.h>
31#include <camera/NdkCameraManager.h>
32#include <media/NdkImage.h>
33#include <media/NdkImageReader.h>
34
36#include "libavformat/demux.h"
38#include "libavutil/avstring.h"
39#include "libavutil/display.h"
40#include "libavutil/imgutils.h"
41#include "libavutil/log.h"
42#include "libavutil/mem.h"
43#include "libavutil/opt.h"
45#include "libavutil/pixfmt.h"
47#include "libavutil/time.h"
48
49/* This image format is available on all Android devices
50 * supporting the Camera2 API */
51#define IMAGE_FORMAT_ANDROID AIMAGE_FORMAT_YUV_420_888
52
53#define MAX_BUF_COUNT 2
54#define VIDEO_STREAM_INDEX 0
55#define VIDEO_TIMEBASE_ANDROID 1000000000
56
57#define RETURN_CASE(x) case x: return AV_STRINGIFY(x);
58#define RETURN_DEFAULT(x) default: return AV_STRINGIFY(x);
59
60typedef struct AndroidCameraCtx {
61 const AVClass *class;
62
68
69 uint8_t lens_facing;
71 int width;
72 int height;
75
76 ACameraManager *camera_mgr;
77 char *camera_id;
78 ACameraMetadata *camera_metadata;
79 ACameraDevice *camera_dev;
80 ACameraDevice_StateCallbacks camera_state_callbacks;
81 AImageReader *image_reader;
82 AImageReader_ImageListener image_listener;
83 ANativeWindow *image_reader_window;
84 ACaptureSessionOutputContainer *capture_session_output_container;
85 ACaptureSessionOutput *capture_session_output;
86 ACameraOutputTarget *camera_output_target;
87 ACaptureRequest *capture_request;
88 ACameraCaptureSession_stateCallbacks capture_session_state_callbacks;
89 ACameraCaptureSession *capture_session;
90
95
96static const char *camera_status_string(camera_status_t val)
97{
98 switch(val) {
99 RETURN_CASE(ACAMERA_OK)
100 RETURN_CASE(ACAMERA_ERROR_UNKNOWN)
101 RETURN_CASE(ACAMERA_ERROR_INVALID_PARAMETER)
102 RETURN_CASE(ACAMERA_ERROR_CAMERA_DISCONNECTED)
103 RETURN_CASE(ACAMERA_ERROR_NOT_ENOUGH_MEMORY)
104 RETURN_CASE(ACAMERA_ERROR_METADATA_NOT_FOUND)
105 RETURN_CASE(ACAMERA_ERROR_CAMERA_DEVICE)
106 RETURN_CASE(ACAMERA_ERROR_CAMERA_SERVICE)
107 RETURN_CASE(ACAMERA_ERROR_SESSION_CLOSED)
108 RETURN_CASE(ACAMERA_ERROR_INVALID_OPERATION)
109 RETURN_CASE(ACAMERA_ERROR_STREAM_CONFIGURE_FAIL)
110 RETURN_CASE(ACAMERA_ERROR_CAMERA_IN_USE)
111 RETURN_CASE(ACAMERA_ERROR_MAX_CAMERA_IN_USE)
112 RETURN_CASE(ACAMERA_ERROR_CAMERA_DISABLED)
113 RETURN_CASE(ACAMERA_ERROR_PERMISSION_DENIED)
114 RETURN_DEFAULT(ACAMERA_ERROR_UNKNOWN)
115 }
116}
117
118static const char *media_status_string(media_status_t val)
119{
120 switch(val) {
121 RETURN_CASE(AMEDIA_OK)
122 RETURN_CASE(AMEDIA_ERROR_UNKNOWN)
123 RETURN_CASE(AMEDIA_ERROR_MALFORMED)
124 RETURN_CASE(AMEDIA_ERROR_UNSUPPORTED)
125 RETURN_CASE(AMEDIA_ERROR_INVALID_OBJECT)
126 RETURN_CASE(AMEDIA_ERROR_INVALID_PARAMETER)
127 RETURN_CASE(AMEDIA_ERROR_INVALID_OPERATION)
128 RETURN_CASE(AMEDIA_DRM_NOT_PROVISIONED)
129 RETURN_CASE(AMEDIA_DRM_RESOURCE_BUSY)
130 RETURN_CASE(AMEDIA_DRM_DEVICE_REVOKED)
131 RETURN_CASE(AMEDIA_DRM_SHORT_BUFFER)
132 RETURN_CASE(AMEDIA_DRM_SESSION_NOT_OPENED)
133 RETURN_CASE(AMEDIA_DRM_TAMPER_DETECTED)
134 RETURN_CASE(AMEDIA_DRM_VERIFY_FAILED)
135 RETURN_CASE(AMEDIA_DRM_NEED_KEY)
136 RETURN_CASE(AMEDIA_DRM_LICENSE_EXPIRED)
137 RETURN_CASE(AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE)
138 RETURN_CASE(AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED)
139 RETURN_CASE(AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE)
140 RETURN_CASE(AMEDIA_IMGREADER_CANNOT_UNLOCK_IMAGE)
141 RETURN_CASE(AMEDIA_IMGREADER_IMAGE_NOT_LOCKED)
142 RETURN_DEFAULT(AMEDIA_ERROR_UNKNOWN)
143 }
144}
145
146static const char *error_state_callback_string(int val)
147{
148 switch(val) {
149 RETURN_CASE(ERROR_CAMERA_IN_USE)
150 RETURN_CASE(ERROR_MAX_CAMERAS_IN_USE)
151 RETURN_CASE(ERROR_CAMERA_DISABLED)
152 RETURN_CASE(ERROR_CAMERA_DEVICE)
153 RETURN_CASE(ERROR_CAMERA_SERVICE)
154 default:
155 return "ERROR_CAMERA_UNKNOWN";
156 }
157}
158
159static void camera_dev_disconnected(void *context, ACameraDevice *device)
160{
161 AVFormatContext *avctx = context;
163 atomic_store(&ctx->exit, 1);
164 av_log(avctx, AV_LOG_ERROR, "Camera with id %s disconnected.\n",
165 ACameraDevice_getId(device));
166}
167
168static void camera_dev_error(void *context, ACameraDevice *device, int error)
169{
170 AVFormatContext *avctx = context;
172 atomic_store(&ctx->exit, 1);
173 av_log(avctx, AV_LOG_ERROR, "Error %s on camera with id %s.\n",
174 error_state_callback_string(error), ACameraDevice_getId(device));
175}
176
177static int open_camera(AVFormatContext *avctx)
178{
180 camera_status_t ret;
181 ACameraIdList *camera_ids;
182
183 ret = ACameraManager_getCameraIdList(ctx->camera_mgr, &camera_ids);
184 if (ret != ACAMERA_OK) {
185 av_log(avctx, AV_LOG_ERROR, "Failed to get camera id list, error: %s.\n",
187 return AVERROR_EXTERNAL;
188 }
189
190 if (ctx->camera_index < camera_ids->numCameras) {
191 ctx->camera_id = av_strdup(camera_ids->cameraIds[ctx->camera_index]);
192 if (!ctx->camera_id) {
193 av_log(avctx, AV_LOG_ERROR, "Failed to allocate memory for camera_id.\n");
194 return AVERROR(ENOMEM);
195 }
196 } else {
197 av_log(avctx, AV_LOG_ERROR, "No camera with index %d available.\n",
198 ctx->camera_index);
199 return AVERROR(ENXIO);
200 }
201
202 ACameraManager_deleteCameraIdList(camera_ids);
203
204 ret = ACameraManager_getCameraCharacteristics(ctx->camera_mgr,
205 ctx->camera_id, &ctx->camera_metadata);
206 if (ret != ACAMERA_OK) {
207 av_log(avctx, AV_LOG_ERROR, "Failed to get metadata for camera with id %s, error: %s.\n",
208 ctx->camera_id, camera_status_string(ret));
209 return AVERROR_EXTERNAL;
210 }
211
212 ctx->camera_state_callbacks.context = avctx;
213 ctx->camera_state_callbacks.onDisconnected = camera_dev_disconnected;
214 ctx->camera_state_callbacks.onError = camera_dev_error;
215
216 ret = ACameraManager_openCamera(ctx->camera_mgr, ctx->camera_id,
217 &ctx->camera_state_callbacks, &ctx->camera_dev);
218 if (ret != ACAMERA_OK) {
219 av_log(avctx, AV_LOG_ERROR, "Failed to open camera with id %s, error: %s.\n",
220 ctx->camera_id, camera_status_string(ret));
221 return AVERROR_EXTERNAL;
222 }
223
224 return 0;
225}
226
228{
230 ACameraMetadata_const_entry lens_facing;
231 ACameraMetadata_const_entry sensor_orientation;
232
233 ACameraMetadata_getConstEntry(ctx->camera_metadata,
234 ACAMERA_LENS_FACING, &lens_facing);
235 ACameraMetadata_getConstEntry(ctx->camera_metadata,
236 ACAMERA_SENSOR_ORIENTATION, &sensor_orientation);
237
238 ctx->lens_facing = lens_facing.data.u8[0];
239 ctx->sensor_orientation = sensor_orientation.data.i32[0];
240}
241
243{
245 ACameraMetadata_const_entry available_configs;
246 int found = 0;
247
248 ACameraMetadata_getConstEntry(ctx->camera_metadata,
249 ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
250 &available_configs);
251
252 for (int i = 0; i < available_configs.count / 4; i++) {
253 int32_t input = available_configs.data.i32[i * 4 + 3];
254 int32_t format = available_configs.data.i32[i * 4 + 0];
255
256 if (input) {
257 continue;
258 }
259
261 int32_t width = available_configs.data.i32[i * 4 + 1];
262 int32_t height = available_configs.data.i32[i * 4 + 2];
263
264 //Same ratio
265 if ((ctx->requested_width == width && ctx->requested_height == height) ||
266 (ctx->requested_width == height && ctx->requested_height == width)) {
267 ctx->width = width;
268 ctx->height = height;
269 found = 1;
270 break;
271 }
272 }
273 }
274
275 if (!found || ctx->width == 0 || ctx->height == 0) {
276 ctx->width = available_configs.data.i32[1];
277 ctx->height = available_configs.data.i32[2];
278
279 av_log(avctx, AV_LOG_WARNING,
280 "Requested video_size %dx%d not available, falling back to %dx%d\n",
281 ctx->requested_width, ctx->requested_height, ctx->width, ctx->height);
282 }
283
284 return;
285}
286
288{
290 ACameraMetadata_const_entry available_framerates;
291 int found = 0;
292 int current_best_match = -1;
293 int requested_framerate = av_q2d(ctx->framerate);
294
295 ACameraMetadata_getConstEntry(ctx->camera_metadata,
296 ACAMERA_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
297 &available_framerates);
298
299 for (int i = 0; i < available_framerates.count / 2; i++) {
300 int32_t min = available_framerates.data.i32[i * 2 + 0];
301 int32_t max = available_framerates.data.i32[i * 2 + 1];
302
303 if (requested_framerate == max) {
304 if (min == max) {
305 ctx->framerate_range[0] = min;
306 ctx->framerate_range[1] = max;
307 found = 1;
308 break;
309 } else if (current_best_match >= 0) {
310 int32_t current_best_match_min = available_framerates.data.i32[current_best_match * 2 + 0];
311 if (min > current_best_match_min) {
312 current_best_match = i;
313 }
314 } else {
315 current_best_match = i;
316 }
317 }
318 }
319
320 if (!found) {
321 if (current_best_match >= 0) {
322 ctx->framerate_range[0] = available_framerates.data.i32[current_best_match * 2 + 0];
323 ctx->framerate_range[1] = available_framerates.data.i32[current_best_match * 2 + 1];
324
325 } else {
326 ctx->framerate_range[0] = available_framerates.data.i32[0];
327 ctx->framerate_range[1] = available_framerates.data.i32[1];
328 }
329
330 av_log(avctx, AV_LOG_WARNING,
331 "Requested framerate %d not available, falling back to min: %d and max: %d fps\n",
332 requested_framerate, ctx->framerate_range[0], ctx->framerate_range[1]);
333 }
334
335 return;
336}
337
338static int get_image_format(AVFormatContext *avctx, AImage *image)
339{
341 int32_t image_pixelstrides[2];
342 uint8_t *image_plane_data[2];
343 int plane_data_length[2];
344
345 for (int i = 0; i < 2; i++) {
346 AImage_getPlanePixelStride(image, i + 1, &image_pixelstrides[i]);
347 AImage_getPlaneData(image, i + 1, &image_plane_data[i], &plane_data_length[i]);
348 }
349
350 if (image_pixelstrides[0] != image_pixelstrides[1]) {
351 av_log(avctx, AV_LOG_ERROR,
352 "Pixel strides of U and V plane should have been the same.\n");
353 return AVERROR_EXTERNAL;
354 }
355
356 switch (image_pixelstrides[0]) {
357 case 1:
358 ctx->image_format = AV_PIX_FMT_YUV420P;
359 break;
360 case 2:
361 if (image_plane_data[0] < image_plane_data[1]) {
362 ctx->image_format = AV_PIX_FMT_NV12;
363 } else {
364 ctx->image_format = AV_PIX_FMT_NV21;
365 }
366 break;
367 default:
368 av_log(avctx, AV_LOG_ERROR,
369 "Unknown pixel stride %d of U and V plane, cannot determine camera image format.\n",
370 image_pixelstrides[0]);
371 return AVERROR(ENOSYS);
372 }
373
374 return 0;
375}
376
377static void image_available(void *context, AImageReader *reader)
378{
379 AVFormatContext *avctx = context;
381 media_status_t media_status;
382 int ret = 0;
383
384 AImage *image;
385 int64_t image_timestamp;
386 int32_t image_linestrides[4];
387 uint8_t *image_plane_data[4];
388 int plane_data_length[4];
389
391 int pkt_buffer_size = 0;
392
393 media_status = AImageReader_acquireLatestImage(reader, &image);
394 if (media_status != AMEDIA_OK) {
395 if (media_status == AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE) {
396 av_log(avctx, AV_LOG_WARNING,
397 "An image reader frame was discarded");
398 } else {
399 av_log(avctx, AV_LOG_ERROR,
400 "Failed to acquire latest image from image reader, error: %s.\n",
401 media_status_string(media_status));
402 ret = AVERROR_EXTERNAL;
403 }
404 goto error;
405 }
406
407 // Silently drop frames when exit is set
408 if (atomic_load(&ctx->exit)) {
409 goto error;
410 }
411
412 // Determine actual image format
413 if (!atomic_load(&ctx->got_image_format)) {
414 ret = get_image_format(avctx, image);
415 if (ret < 0) {
416 av_log(avctx, AV_LOG_ERROR,
417 "Could not get image format of camera.\n");
418 goto error;
419 } else {
420 atomic_store(&ctx->got_image_format, 1);
421 }
422 }
423
424 pkt_buffer_size = av_image_get_buffer_size(ctx->image_format, ctx->width, ctx->height, 1);
425 AImage_getTimestamp(image, &image_timestamp);
426
427 AImage_getPlaneRowStride(image, 0, &image_linestrides[0]);
428 AImage_getPlaneData(image, 0, &image_plane_data[0], &plane_data_length[0]);
429
430 switch (ctx->image_format) {
432 AImage_getPlaneRowStride(image, 1, &image_linestrides[1]);
433 AImage_getPlaneData(image, 1, &image_plane_data[1], &plane_data_length[1]);
434 AImage_getPlaneRowStride(image, 2, &image_linestrides[2]);
435 AImage_getPlaneData(image, 2, &image_plane_data[2], &plane_data_length[2]);
436 break;
437 case AV_PIX_FMT_NV12:
438 AImage_getPlaneRowStride(image, 1, &image_linestrides[1]);
439 AImage_getPlaneData(image, 1, &image_plane_data[1], &plane_data_length[1]);
440 break;
441 case AV_PIX_FMT_NV21:
442 AImage_getPlaneRowStride(image, 2, &image_linestrides[1]);
443 AImage_getPlaneData(image, 2, &image_plane_data[1], &plane_data_length[1]);
444 break;
445 default:
446 av_log(avctx, AV_LOG_ERROR, "Unsupported camera image format.\n");
447 ret = AVERROR(ENOSYS);
448 goto error;
449 }
450
451 ret = av_new_packet(&pkt, pkt_buffer_size);
452 if (ret < 0) {
453 av_log(avctx, AV_LOG_ERROR,
454 "Failed to create new av packet, error: %s.\n", av_err2str(ret));
455 goto error;
456 }
457
458 pkt.stream_index = VIDEO_STREAM_INDEX;
459 pkt.pts = image_timestamp;
460 av_image_copy_to_buffer(pkt.data, pkt_buffer_size,
461 (const uint8_t * const *) image_plane_data,
462 image_linestrides, ctx->image_format,
463 ctx->width, ctx->height, 1);
464
466
467error:
468 if (ret < 0) {
469 if (ret != AVERROR(EAGAIN)) {
470 av_log(avctx, AV_LOG_ERROR,
471 "Error while processing new image, error: %s.\n", av_err2str(ret));
472 av_thread_message_queue_set_err_recv(ctx->input_queue, ret);
473 atomic_store(&ctx->exit, 1);
474 } else {
475 av_log(avctx, AV_LOG_WARNING,
476 "Input queue was full, dropping frame, consider raising the input_queue_size option (current value: %d)\n",
477 ctx->input_queue_size);
478 }
479 if (pkt_buffer_size) {
481 }
482 }
483
484 AImage_delete(image);
485
486 return;
487}
488
490{
492 media_status_t ret;
493
494 ret = AImageReader_new(ctx->width, ctx->height, IMAGE_FORMAT_ANDROID,
495 MAX_BUF_COUNT, &ctx->image_reader);
496 if (ret != AMEDIA_OK) {
497 av_log(avctx, AV_LOG_ERROR,
498 "Failed to create image reader, error: %s.\n", media_status_string(ret));
499 return AVERROR_EXTERNAL;
500 }
501
502 ctx->image_listener.context = avctx;
503 ctx->image_listener.onImageAvailable = image_available;
504
505 ret = AImageReader_setImageListener(ctx->image_reader, &ctx->image_listener);
506 if (ret != AMEDIA_OK) {
507 av_log(avctx, AV_LOG_ERROR,
508 "Failed to set image listener on image reader, error: %s.\n",
510 return AVERROR_EXTERNAL;
511 }
512
513 ret = AImageReader_getWindow(ctx->image_reader, &ctx->image_reader_window);
514 if (ret != AMEDIA_OK) {
515 av_log(avctx, AV_LOG_ERROR,
516 "Could not get image reader window, error: %s.\n",
518 return AVERROR_EXTERNAL;
519 }
520
521 return 0;
522}
523
524static void capture_session_closed(void *context, ACameraCaptureSession *session)
525{
526 av_log(context, AV_LOG_INFO, "Android camera capture session was closed.\n");
527}
528
529static void capture_session_ready(void *context, ACameraCaptureSession *session)
530{
531 av_log(context, AV_LOG_INFO, "Android camera capture session is ready.\n");
532}
533
534static void capture_session_active(void *context, ACameraCaptureSession *session)
535{
536 av_log(context, AV_LOG_INFO, "Android camera capture session is active.\n");
537}
538
540{
542 camera_status_t ret;
543
544 ret = ACaptureSessionOutputContainer_create(&ctx->capture_session_output_container);
545 if (ret != ACAMERA_OK) {
546 av_log(avctx, AV_LOG_ERROR,
547 "Failed to create capture session output container, error: %s.\n",
549 return AVERROR_EXTERNAL;
550 }
551
552 ANativeWindow_acquire(ctx->image_reader_window);
553
554 ret = ACaptureSessionOutput_create(ctx->image_reader_window, &ctx->capture_session_output);
555 if (ret != ACAMERA_OK) {
556 av_log(avctx, AV_LOG_ERROR,
557 "Failed to create capture session container, error: %s.\n",
559 return AVERROR_EXTERNAL;
560 }
561
562 ret = ACaptureSessionOutputContainer_add(ctx->capture_session_output_container,
563 ctx->capture_session_output);
564 if (ret != ACAMERA_OK) {
565 av_log(avctx, AV_LOG_ERROR,
566 "Failed to add output to output container, error: %s.\n",
568 return AVERROR_EXTERNAL;
569 }
570
571 ret = ACameraOutputTarget_create(ctx->image_reader_window, &ctx->camera_output_target);
572 if (ret != ACAMERA_OK) {
573 av_log(avctx, AV_LOG_ERROR,
574 "Failed to create camera output target, error: %s.\n",
576 return AVERROR_EXTERNAL;
577 }
578
579 ret = ACameraDevice_createCaptureRequest(ctx->camera_dev, TEMPLATE_RECORD, &ctx->capture_request);
580 if (ret != ACAMERA_OK) {
581 av_log(avctx, AV_LOG_ERROR,
582 "Failed to create capture request, error: %s.\n",
584 return AVERROR_EXTERNAL;
585 }
586
587 ret = ACaptureRequest_setEntry_i32(ctx->capture_request, ACAMERA_CONTROL_AE_TARGET_FPS_RANGE,
588 2, ctx->framerate_range);
589 if (ret != ACAMERA_OK) {
590 av_log(avctx, AV_LOG_ERROR,
591 "Failed to set target fps range in capture request, error: %s.\n",
593 return AVERROR_EXTERNAL;
594 }
595
596 ret = ACaptureRequest_addTarget(ctx->capture_request, ctx->camera_output_target);
597 if (ret != ACAMERA_OK) {
598 av_log(avctx, AV_LOG_ERROR,
599 "Failed to add capture request capture request, error: %s.\n",
601 return AVERROR_EXTERNAL;
602 }
603
604 ctx->capture_session_state_callbacks.context = avctx;
605 ctx->capture_session_state_callbacks.onClosed = capture_session_closed;
606 ctx->capture_session_state_callbacks.onReady = capture_session_ready;
607 ctx->capture_session_state_callbacks.onActive = capture_session_active;
608
609 ret = ACameraDevice_createCaptureSession(ctx->camera_dev, ctx->capture_session_output_container,
610 &ctx->capture_session_state_callbacks, &ctx->capture_session);
611 if (ret != ACAMERA_OK) {
612 av_log(avctx, AV_LOG_ERROR,
613 "Failed to create capture session, error: %s.\n",
615 return AVERROR_EXTERNAL;
616 }
617
618 ret = ACameraCaptureSession_setRepeatingRequest(ctx->capture_session, NULL, 1, &ctx->capture_request, NULL);
619 if (ret != ACAMERA_OK) {
620 av_log(avctx, AV_LOG_ERROR,
621 "Failed to set repeating request on capture session, error: %s.\n",
623 return AVERROR_EXTERNAL;
624 }
625
626 return 0;
627}
628
630{
632
633 while (!atomic_load(&ctx->got_image_format) && !atomic_load(&ctx->exit)) {
634 //Wait until first frame arrived and actual image format was determined
635 usleep(1000);
636 }
637
638 return atomic_load(&ctx->got_image_format);
639}
640
642{
644 AVPacketSideData *side_data;
645 int32_t display_matrix[9];
646
647 av_display_rotation_set(display_matrix, ctx->sensor_orientation);
648
649 if (ctx->lens_facing == ACAMERA_LENS_FACING_FRONT) {
650 av_display_matrix_flip(display_matrix, 1, 0);
651 }
652
656 sizeof(display_matrix), 0);
657
658 if (!side_data) {
659 return AVERROR(ENOMEM);
660 }
661
662 memcpy(side_data->data, display_matrix, sizeof(display_matrix));
663
664 return 0;
665}
666
668{
670 AVStream *st;
671 AVCodecParameters *codecpar;
672
673 st = avformat_new_stream(avctx, NULL);
674 if (!st) {
675 return AVERROR(ENOMEM);
676 }
677
679 st->avg_frame_rate = (AVRational) { ctx->framerate_range[1], 1 };
680 st->r_frame_rate = (AVRational) { ctx->framerate_range[1], 1 };
681
682 if (!wait_for_image_format(avctx)) {
683 return AVERROR_EXTERNAL;
684 }
685
686 codecpar = st->codecpar;
687 codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
688 codecpar->codec_id = AV_CODEC_ID_RAWVIDEO;
689 codecpar->format = ctx->image_format;
690 codecpar->width = ctx->width;
691 codecpar->height = ctx->height;
692
694
695 return add_display_matrix(avctx, st);
696}
697
699{
701
702 atomic_store(&ctx->exit, 1);
703
704 if (ctx->capture_session) {
705 ACameraCaptureSession_stopRepeating(ctx->capture_session);
706 // Following warning is emitted, after capture session closed callback is received:
707 // ACameraCaptureSession: Device is closed but session 0 is not notified
708 // Seems to be a bug in Android, we can ignore this
709 ACameraCaptureSession_close(ctx->capture_session);
710 ctx->capture_session = NULL;
711 }
712
713 if (ctx->capture_request) {
714 ACaptureRequest_removeTarget(ctx->capture_request, ctx->camera_output_target);
715 ACaptureRequest_free(ctx->capture_request);
716 ctx->capture_request = NULL;
717 }
718
719 if (ctx->camera_output_target) {
720 ACameraOutputTarget_free(ctx->camera_output_target);
721 ctx->camera_output_target = NULL;
722 }
723
724 if (ctx->capture_session_output) {
725 ACaptureSessionOutputContainer_remove(ctx->capture_session_output_container,
726 ctx->capture_session_output);
727 ACaptureSessionOutput_free(ctx->capture_session_output);
728 ctx->capture_session_output = NULL;
729 }
730
731 if (ctx->image_reader_window) {
732 ANativeWindow_release(ctx->image_reader_window);
733 ctx->image_reader_window = NULL;
734 }
735
736 if (ctx->capture_session_output_container) {
737 ACaptureSessionOutputContainer_free(ctx->capture_session_output_container);
738 ctx->capture_session_output_container = NULL;
739 }
740
741 if (ctx->camera_dev) {
742 ACameraDevice_close(ctx->camera_dev);
743 ctx->camera_dev = NULL;
744 }
745
746 if (ctx->image_reader) {
747 AImageReader_delete(ctx->image_reader);
748 ctx->image_reader = NULL;
749 }
750
751 if (ctx->camera_metadata) {
752 ACameraMetadata_free(ctx->camera_metadata);
753 ctx->camera_metadata = NULL;
754 }
755
756 av_freep(&ctx->camera_id);
757
758 if (ctx->camera_mgr) {
759 ACameraManager_delete(ctx->camera_mgr);
760 ctx->camera_mgr = NULL;
761 }
762
763 if (ctx->input_queue) {
766 while (av_thread_message_queue_recv(ctx->input_queue, &pkt, AV_THREAD_MESSAGE_NONBLOCK) >= 0) {
768 }
769 av_thread_message_queue_free(&ctx->input_queue);
770 }
771
772 return 0;
773}
774
776{
778 int ret;
779
780 atomic_init(&ctx->got_image_format, 0);
781 atomic_init(&ctx->exit, 0);
782
783 ret = av_thread_message_queue_alloc(&ctx->input_queue, ctx->input_queue_size, sizeof(AVPacket));
784 if (ret < 0) {
785 av_log(avctx, AV_LOG_ERROR,
786 "Failed to allocate input queue, error: %s.\n", av_err2str(ret));
787 goto error;
788 }
789
790 ctx->camera_mgr = ACameraManager_create();
791 if (!ctx->camera_mgr) {
792 av_log(avctx, AV_LOG_ERROR, "Failed to create Android camera manager.\n");
793 ret = AVERROR_EXTERNAL;
794 goto error;
795 }
796
797 ret = open_camera(avctx);
798 if (ret < 0) {
799 av_log(avctx, AV_LOG_ERROR, "Failed to open camera.\n");
800 goto error;
801 }
802
804 match_video_size(avctx);
805 match_framerate(avctx);
806
807 ret = create_image_reader(avctx);
808 if (ret < 0) {
809 goto error;
810 }
811
812 ret = create_capture_session(avctx);
813 if (ret < 0) {
814 goto error;
815 }
816
817 ret = add_video_stream(avctx);
818
819error:
820 if (ret < 0) {
822 av_log(avctx, AV_LOG_ERROR, "Failed to open android_camera.\n");
823 }
824
825 return ret;
826}
827
829{
831 int ret;
832
833 if (!atomic_load(&ctx->exit)) {
834 ret = av_thread_message_queue_recv(ctx->input_queue, pkt,
836 } else {
837 ret = AVERROR_EOF;
838 }
839
840 if (ret < 0) {
841 return ret;
842 } else {
843 return pkt->size;
844 }
845}
846
847#define OFFSET(x) offsetof(AndroidCameraCtx, x)
848#define DEC AV_OPT_FLAG_DECODING_PARAM
849static const AVOption options[] = {
850 { "video_size", "set video size given as a string such as 640x480 or hd720", OFFSET(requested_width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC },
851 { "framerate", "set video frame rate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "30"}, 0, INT_MAX, DEC },
852 { "camera_index", "set index of camera to use", OFFSET(camera_index), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
853 { "input_queue_size", "set maximum number of frames to buffer", OFFSET(input_queue_size), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, DEC },
854 { NULL },
855};
856
858 .class_name = "android_camera indev",
859 .item_name = av_default_item_name,
860 .option = options,
861 .version = LIBAVUTIL_VERSION_INT,
863};
864
866 .p.name = "android_camera",
867 .p.long_name = NULL_IF_CONFIG_SMALL("Android camera input device"),
868 .p.flags = AVFMT_NOFILE,
869 .p.priv_class = &android_camera_class,
870 .priv_data_size = sizeof(AndroidCameraCtx),
874};
static double val(void *priv, double ch)
Definition aeval.c:77
static const char *const format[]
Definition af_aiir.c:444
const FFInputFormat ff_android_camera_demuxer
#define RETURN_CASE(x)
static void image_available(void *context, AImageReader *reader)
static int android_camera_read_header(AVFormatContext *avctx)
static void capture_session_active(void *context, ACameraCaptureSession *session)
#define RETURN_DEFAULT(x)
static const char * media_status_string(media_status_t val)
static int add_video_stream(AVFormatContext *avctx)
static int get_image_format(AVFormatContext *avctx, AImage *image)
static void camera_dev_error(void *context, ACameraDevice *device, int error)
#define IMAGE_FORMAT_ANDROID
#define VIDEO_STREAM_INDEX
static void camera_dev_disconnected(void *context, ACameraDevice *device)
#define VIDEO_TIMEBASE_ANDROID
static int android_camera_read_packet(AVFormatContext *avctx, AVPacket *pkt)
static int create_image_reader(AVFormatContext *avctx)
static void get_sensor_orientation(AVFormatContext *avctx)
static int open_camera(AVFormatContext *avctx)
static void capture_session_ready(void *context, ACameraCaptureSession *session)
static int wait_for_image_format(AVFormatContext *avctx)
static void capture_session_closed(void *context, ACameraCaptureSession *session)
static const char * error_state_callback_string(int val)
#define OFFSET(x)
static int android_camera_read_close(AVFormatContext *avctx)
#define MAX_BUF_COUNT
static int create_capture_session(AVFormatContext *avctx)
static const AVClass android_camera_class
static void match_framerate(AVFormatContext *avctx)
static void match_video_size(AVFormatContext *avctx)
static int add_display_matrix(AVFormatContext *avctx, AVStream *st)
static const char * camera_status_string(camera_status_t val)
int32_t
void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition avformat.c:834
Main libavformat public API header.
#define AVFMT_FLAG_NONBLOCK
Do not block when reading packets from input.
Definition avformat.h:1487
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition avformat.h:488
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
#define min(a, b)
#define max(a, b)
static AVPacket * pkt
Display matrix.
#define atomic_store(object, desired)
Definition stdatomic.h:85
intptr_t atomic_int
Definition stdatomic.h:55
#define atomic_load(object)
Definition stdatomic.h:93
#define atomic_init(obj, value)
Definition stdatomic.h:33
static int read_header(FFV1Context *f, RangeCoder *c)
Definition ffv1dec.c:578
@ AV_OPT_TYPE_IMAGE_SIZE
Underlying C type is two consecutive integers.
Definition opt.h:302
@ AV_OPT_TYPE_VIDEO_RATE
Underlying C type is AVRational.
Definition opt.h:314
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_CODEC_ID_RAWVIDEO
Definition codec_id.h:63
AVPacketSideData * av_packet_side_data_new(AVPacketSideData **psd, int *pnb_sd, enum AVPacketSideDataType type, size_t size, int flags)
Allocate a new packet side data.
Definition packet.c:620
@ AV_PKT_DATA_DISPLAYMATRIX
This side data contains a 3x3 transformation matrix describing an affine transformation that needs to...
Definition packet.h:105
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition packet.c:434
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition packet.c:98
AVStream * avformat_new_stream(AVFormatContext *s, const struct AVCodec *c)
Add a new stream to a media file.
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition error.h:59
#define AVERROR_EOF
End of file.
Definition error.h:57
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition error.h:122
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_INFO
Standard information.
Definition log.h:221
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:241
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition rational.h:104
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
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.
Definition imgutils.c:466
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.
Definition imgutils.c:501
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
void av_display_rotation_set(int32_t matrix[9], double angle)
Initialize a transformation matrix describing a pure clockwise rotation by the specified angle (in de...
Definition display.c:51
void av_display_matrix_flip(int32_t matrix[9], int hflip, int vflip)
Flip the input matrix horizontally and/or vertically.
Definition display.c:66
misc image utilities
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
static av_cold int read_close(AVFormatContext *ctx)
Definition libcdio.c:143
#define DEC
Definition librsvgdec.c:149
@ AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT
Definition log.h:42
Memory handling functions.
#define av_strdup(s)
Definition ops_static.c:55
AVOptions.
misc parsing utilities
pixel format definitions
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition pixfmt.h:96
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
@ AV_PIX_FMT_NV21
as above, but U and V bytes are swapped
Definition pixfmt.h:97
Describe the class of an AVClass context structure.
Definition log.h:76
This struct describes the properties of an encoded stream.
Definition codec_par.h:49
int height
The height of the video frame in pixels.
Definition codec_par.h:150
int nb_coded_side_data
Amount of entries in coded_side_data.
Definition codec_par.h:88
int width
The width of the video frame in pixels.
Definition codec_par.h:143
enum AVMediaType codec_type
General type of the encoded data.
Definition codec_par.h:53
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition codec_par.h:57
AVPacketSideData * coded_side_data
Additional data associated with the entire stream.
Definition codec_par.h:83
Format I/O context.
Definition avformat.h:1333
int flags
Flags modifying the (de)muxer behaviour.
Definition avformat.h:1484
void * priv_data
Format private data.
Definition avformat.h:1361
AVOption.
Definition opt.h:428
This structure stores auxiliary information for decoding, presenting, or otherwise processing the cod...
Definition packet.h:424
uint8_t * data
Definition packet.h:425
This structure stores compressed data.
Definition packet.h:580
Rational number (pair of numerator and denominator).
Definition rational.h:58
Stream structure.
Definition avformat.h:766
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition avformat.h:789
int id
Format-specific stream ID.
Definition avformat.h:778
AVRational avg_frame_rate
Average framerate.
Definition avformat.h:855
AVRational r_frame_rate
Real base framerate of the stream.
Definition avformat.h:900
ACameraDevice_StateCallbacks camera_state_callbacks
AVRational framerate
atomic_int got_image_format
ANativeWindow * image_reader_window
ACameraCaptureSession_stateCallbacks capture_session_state_callbacks
ACameraCaptureSession * capture_session
AImageReader_ImageListener image_listener
ACameraManager * camera_mgr
int32_t framerate_range[2]
ACameraDevice * camera_dev
ACameraOutputTarget * camera_output_target
AImageReader * image_reader
ACameraMetadata * camera_metadata
AVThreadMessageQueue * input_queue
int32_t sensor_orientation
ACaptureRequest * capture_request
ACaptureSessionOutputContainer * capture_session_output_container
ACaptureSessionOutput * capture_session_output
#define av_freep(p)
#define av_log(a,...)
static void error(const char *err)
float framerate
Definition av1_levels.c:29
static AVFormatContext * ctx
Definition movenc.c:49
#define height
Definition dsp.h:89
#define width
Definition dsp.h:89
void av_thread_message_queue_set_err_send(AVThreadMessageQueue *mq, int err)
Set the sending error code.
int av_thread_message_queue_recv(AVThreadMessageQueue *mq, void *msg, unsigned flags)
Receive a message from the queue.
int av_thread_message_queue_alloc(AVThreadMessageQueue **mq, unsigned nelem, unsigned elsize)
Allocate a new message queue.
void av_thread_message_queue_set_err_recv(AVThreadMessageQueue *mq, int err)
Set the receiving error code.
int av_thread_message_queue_send(AVThreadMessageQueue *mq, void *msg, unsigned flags)
Send a message on the queue.
void av_thread_message_queue_free(AVThreadMessageQueue **mq)
Free a message queue.
@ AV_THREAD_MESSAGE_NONBLOCK
Perform non-blocking operation.