blob: d22ed7d0de5f544ed10d0bc5131f79a8489feb32 [file] [log] [blame]
Owen Lin133ed582016-08-15 11:47:39 +08001/* Copyright 2014 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6#include <assert.h>
7#include <errno.h>
8#include <linux/videodev2.h>
9#include <pthread.h>
10#include <unistd.h>
11#include <stdbool.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <sys/queue.h>
16#include <sys/syscall.h>
17#include "config.h" /* For HAVE_VISIBILITY */
18#include "libv4l-plugin.h"
19#include "libvepu/rk_vepu_debug.h"
20#include "libvepu/rk_vepu_interface.h"
21
22#define VLOG(log_level, str, ...) ((g_log_level >= log_level) ? \
23 (void) fprintf(stderr, "%s: " str "\n", __func__, ##__VA_ARGS__) \
24 : (void) 0)
25
26#define VLOG_FD(log_level, str, ...) ((g_log_level >= log_level) ? \
27 (void) fprintf(stderr, \
28 "%s: fd=%d. " str "\n", __func__, fd, ##__VA_ARGS__) : (void) 0)
29
30#define SYS_IOCTL(fd, cmd, arg) ({ \
31 int ret = syscall(SYS_ioctl, (int)(fd), (unsigned long)(cmd), \
32 (void *)(arg)); \
33 if ((ret && errno != EAGAIN) || g_log_level >= 2) \
34 fprintf(stderr, "SYS_ioctl: %s(%lu): fd=%d, ret=%d, errno=%d\n",\
35 v4l_cmd2str(cmd), _IOC_NR((unsigned long)cmd), fd, ret, \
36 errno); \
37 ret; \
38 })
39
40#if HAVE_VISIBILITY
41#define PLUGIN_PUBLIC __attribute__ ((__visibility__("default")))
42#else
43#define PLUGIN_PUBLIC
44#endif
45
46#define DEFAULT_FRAME_RATE 30
47#define DEFAULT_BITRATE 1000000
48#define PENDING_BUFFER_QUEUE_SIZE VIDEO_MAX_FRAME
49
50/*
51 * struct pending_buffer - A v4l2 buffer pending for QBUF.
52 * @buffer: v4l2 buffer for QBUF.
53 * @planes: plane info of v4l2 buffer.
54 * @next_runtime_param: runtime parameters like framerate, bitrate, and
55 * keyframe for the next buffer.
56 */
57struct pending_buffer {
58 struct v4l2_buffer buffer;
59 struct v4l2_plane planes[VIDEO_MAX_PLANES];
60 struct rk_vepu_runtime_param next_runtime_param;
61};
62
63/*
64 * struct pending_buffer_queue - a ring buffer of pending buffers.
65 * @count: the number of buffers stored in the array.
66 * @front: the index of the first ready buffer.
67 * @buf_array: pending buffer array.
68 */
69struct pending_buffer_queue {
70 uint32_t count;
71 int32_t front;
72 struct pending_buffer buf_array[PENDING_BUFFER_QUEUE_SIZE];
73};
74
75/*
76 * struct encoder_context - the context of an encoder instance.
77 * @enc: Encoder instance returned from rk_vepu_create().
78 * @mutex: The mutex to protect encoder_context.
79 * @output_streamon_type: Type of output interface when it streams on.
80 * @capture_streamon_type: Type of capture interface when it streams on.
81 * @init_param: Encoding parameters like input format, resolution, and etc.
82 * These parameters will be passed to encoder at libvpu
83 * initialization.
84 * @runtime_param: Runtime parameters like framerate, bitrate, and
85 * keyframe. This is only used for receiving ext_ctrls
86 * before streamon and pending buffer queue is empty.
87 * @pending_buffers: The pending v4l2 buffers waiting for the encoding
88 * configuration. After a previous buffer is dequeued,
89 * one buffer from the queue can be queued.
90 * @can_qbuf: Indicate that we can queue one source buffer. This is true only
91 * when the parameters to pass together with the source buffer are
92 * ready; those params are received on dequeing the previous
93 * destination buffer.
94 * @get_param_payload: Payload of V4L2_CID_PRIVATE_ROCKCHIP_GET_PARAMS. This is
95 * used to update the encoder configuration by
96 * rk_vepu_update_config().
97 * @get_param_payload_size: The size of get_param_payload.
98 * @v4l2_ctrls: v4l2 controls for VIDIOC_S_EXT_CTRLS.
99 */
100struct encoder_context {
101 void *enc;
102 pthread_mutex_t mutex;
103 enum v4l2_buf_type output_streamon_type;
104 enum v4l2_buf_type capture_streamon_type;
105 struct rk_vepu_init_param init_param;
106 struct rk_vepu_runtime_param runtime_param;
107 struct pending_buffer_queue pending_buffers;
108 bool can_qbuf;
109 void *get_param_payload;
110 size_t get_param_payload_size;
111 struct v4l2_ext_control v4l2_ctrls[MAX_NUM_GET_CONFIG_CTRLS];
112};
113
114static void *plugin_init(int fd);
115static void plugin_close(void *dev_ops_priv);
116static int plugin_ioctl(void *dev_ops_priv, int fd, unsigned long int cmd,
117 void *arg);
118
119/* Functions to handle various ioctl. */
120static int ioctl_streamon_locked(
121 struct encoder_context *ctx, int fd, enum v4l2_buf_type *type);
122static int ioctl_streamoff_locked(
123 struct encoder_context *ctx, int fd, enum v4l2_buf_type *type);
124static int ioctl_qbuf_locked(struct encoder_context *ctx, int fd,
125 struct v4l2_buffer *buffer);
126static int ioctl_dqbuf_locked(struct encoder_context *ctx, int fd,
127 struct v4l2_buffer *buffer);
128static int ioctl_s_ext_ctrls_locked(struct encoder_context *ctx, int fd,
129 struct v4l2_ext_controls *ext_ctrls);
130static int ioctl_s_parm_locked(struct encoder_context *ctx, int fd,
131 struct v4l2_streamparm *parms);
132static int ioctl_reqbufs_locked(struct encoder_context *ctx, int fd,
133 struct v4l2_requestbuffers *reqbufs);
134
135/* Helper functions to manipulate the pending buffer queue. */
136
137static void queue_init(struct pending_buffer_queue *queue);
138static bool queue_empty(struct pending_buffer_queue *queue);
139static bool queue_full(struct pending_buffer_queue *queue);
140/* Insert a buffer to the tail of the queue. */
141static int queue_push_back(struct pending_buffer_queue *queue,
142 struct v4l2_buffer *buffer);
143/* Remove a buffer from the head of the queue. */
144static void queue_pop_front(struct pending_buffer_queue *queue);
145static struct pending_buffer *queue_front(struct pending_buffer_queue *queue);
146static struct pending_buffer *queue_back(struct pending_buffer_queue *queue);
147
148/* Returns true if the fd is Rockchip encoder device. */
149bool is_rockchip_encoder(int fd);
150/* Set encoder configuration to the driver. */
151int set_encoder_config_locked(struct encoder_context *ctx, int fd,
152 uint32_t buffer_index, size_t num_ctrls, uint32_t ctrls_ids[],
153 void **payloads, uint32_t payload_sizes[]);
154/* QBUF a buffer from the pending buffer queue if it is not empty. */
155static int qbuf_if_pending_buffer_exists_locked(struct encoder_context *ctx,
156 int fd);
157/* Get the encoder parameters using G_FMT and initialize libvpu. */
158static int initialize_libvpu(struct encoder_context *ctx, int fd);
159/* Return the string represenation of a libv4l command for debugging. */
160static const char *v4l_cmd2str(unsigned long int cmd);
161/* Get the log level from the environment variable LIBV4L_PLUGIN_LOG_LEVEL. */
162static void get_log_level();
163static pthread_once_t g_get_log_level_once = PTHREAD_ONCE_INIT;
164
165static void *plugin_init(int fd)
166{
167 int ret;
168 struct v4l2_query_ext_ctrl ext_ctrl;
169
170 pthread_once(&g_get_log_level_once, get_log_level);
171
172 VLOG_FD(1, "");
173 if (!is_rockchip_encoder(fd))
174 return NULL;
175
176 struct encoder_context *ctx = (struct encoder_context *)
177 calloc(1, sizeof(struct encoder_context));
178 if (ctx == NULL) {
179 errno = ENOMEM;
180 return NULL;
181 }
182 ret = pthread_mutex_init(&ctx->mutex, NULL);
183 if (ret) {
184 free(ctx);
185 return NULL;
186 }
187 queue_init(&ctx->pending_buffers);
188
189 memset(&ext_ctrl, 0, sizeof(ext_ctrl));
190 ext_ctrl.id = V4L2_CID_PRIVATE_ROCKCHIP_GET_PARAMS;
191 ret = SYS_IOCTL(fd, VIDIOC_QUERY_EXT_CTRL, &ext_ctrl);
192 if (ret) {
193 goto fail;
194 }
195 ctx->get_param_payload_size = ext_ctrl.elem_size;
196 ctx->get_param_payload = calloc(1, ctx->get_param_payload_size);
197 if (ctx->get_param_payload == NULL) {
198 errno = ENOMEM;
199 goto fail;
200 }
201 ctx->runtime_param.framerate_numer = DEFAULT_FRAME_RATE;
202 ctx->runtime_param.framerate_denom = 1;
203 ctx->runtime_param.bitrate = DEFAULT_BITRATE;
204 VLOG_FD(1, "Success. ctx=%p", ctx);
205 return ctx;
206
207fail:
208 plugin_close(ctx);
209 return NULL;
210}
211
212static void plugin_close(void *dev_ops_priv)
213{
214 struct encoder_context *ctx = (struct encoder_context *)dev_ops_priv;
215
216 VLOG(1, "ctx=%p", ctx);
217 if (ctx == NULL)
218 return;
219
220 pthread_mutex_lock(&ctx->mutex);
221 if (ctx->enc)
222 rk_vepu_deinit(ctx->enc);
223 free(ctx->get_param_payload);
224 ctx->get_param_payload = NULL;
225 pthread_mutex_unlock(&ctx->mutex);
226 pthread_mutex_destroy(&ctx->mutex);
227
228 free(ctx);
229}
230
231static int plugin_ioctl(void *dev_ops_priv, int fd,
232 unsigned long int cmd, void *arg)
233{
234 int ret;
235 struct encoder_context *ctx = (struct encoder_context *)dev_ops_priv;
236
237 VLOG_FD(2, "%s(%lu)", v4l_cmd2str(cmd), _IOC_NR(cmd));
238
239 pthread_mutex_lock(&ctx->mutex);
240 switch (cmd) {
241 case VIDIOC_STREAMON:
242 ret = ioctl_streamon_locked(ctx, fd, arg);
243 break;
244
245 case VIDIOC_STREAMOFF:
246 ret = ioctl_streamoff_locked(ctx, fd, arg);
247 break;
248
249 case VIDIOC_QBUF:
250 ret = ioctl_qbuf_locked(ctx, fd, arg);
251 break;
252
253 case VIDIOC_DQBUF:
254 ret = ioctl_dqbuf_locked(ctx, fd, arg);
255 break;
256
257 case VIDIOC_S_EXT_CTRLS:
258 ret = ioctl_s_ext_ctrls_locked(ctx, fd, arg);
259 break;
260
261 case VIDIOC_S_PARM:
262 ret = ioctl_s_parm_locked(ctx, fd, arg);
263 break;
264
265 case VIDIOC_REQBUFS:
266 ret = ioctl_reqbufs_locked(ctx, fd, arg);
267 break;
268
269 default:
270 ret = SYS_IOCTL(fd, cmd, arg);
271 break;
272 }
273 pthread_mutex_unlock(&ctx->mutex);
274 return ret;
275}
276
277static int ioctl_streamon_locked(
278 struct encoder_context *ctx, int fd, enum v4l2_buf_type *type)
279{
280 int ret = SYS_IOCTL(fd, VIDIOC_STREAMON, type);
281 if (ret)
282 return ret;
283
284 if (V4L2_TYPE_IS_OUTPUT(*type))
285 ctx->output_streamon_type = *type;
286 else
287 ctx->capture_streamon_type = *type;
288 if (ctx->output_streamon_type && ctx->capture_streamon_type) {
289 ret = initialize_libvpu(ctx, fd);
290 if (ret)
291 return ret;
292 ctx->can_qbuf = true;
293 return qbuf_if_pending_buffer_exists_locked(ctx, fd);
294 }
295 return 0;
296}
297
298static int ioctl_streamoff_locked(
299 struct encoder_context *ctx, int fd, enum v4l2_buf_type *type)
300{
301 int ret = SYS_IOCTL(fd, VIDIOC_STREAMOFF, type);
302 if (ret)
303 return ret;
304
305 if (V4L2_TYPE_IS_OUTPUT(*type))
306 ctx->output_streamon_type = 0;
307 else
308 ctx->capture_streamon_type = 0;
309 return 0;
310}
311
312static int ioctl_qbuf_locked(struct encoder_context *ctx, int fd,
313 struct v4l2_buffer *buffer)
314{
315 size_t num_ctrls = 0;
316 uint32_t *ctrl_ids = NULL, *payload_sizes = NULL;
317 void **payloads = NULL;
318 int ret;
319
320 if (!V4L2_TYPE_IS_OUTPUT(buffer->type)) {
321 return SYS_IOCTL(fd, VIDIOC_QBUF, buffer);
322 }
323
324 if (!ctx->can_qbuf) {
325 VLOG_FD(1, "Put buffer (%d) in the pending queue.",
326 buffer->index);
327 /*
328 * The last frame is not encoded yet. Put the buffer to the
329 * pending queue.
330 */
331 return queue_push_back(&ctx->pending_buffers, buffer);
332 }
333 /* Get the encoder configuration from the library. */
334 if (rk_vepu_get_config(ctx->enc, &num_ctrls, &ctrl_ids, &payloads,
335 &payload_sizes)) {
336 VLOG_FD(0, "rk_vepu_get_config failed");
337 return -EIO;
338 }
339 /* Set the encoder configuration to the driver. */
340 ret = set_encoder_config_locked(ctx, fd, buffer->index, num_ctrls, ctrl_ids,
341 payloads, payload_sizes);
342 if (ret)
343 return ret;
344
345 buffer->config_store = buffer->index + 1;
346 ret = SYS_IOCTL(fd, VIDIOC_QBUF, buffer);
347 if (ret == 0)
348 ctx->can_qbuf = false;
349 else
350 VLOG(0, "QBUF failed. errno=%d", errno);
351 return ret;
352}
353
354static int ioctl_dqbuf_locked(struct encoder_context *ctx, int fd,
355 struct v4l2_buffer *buffer)
356{
357 struct v4l2_ext_controls ext_ctrls;
358 struct v4l2_ext_control v4l2_ctrl;
359 int ret;
360 uint32_t bytesused;
361
362 if (V4L2_TYPE_IS_OUTPUT(buffer->type)) {
363 return SYS_IOCTL(fd, VIDIOC_DQBUF, buffer);
364 }
365
366 ret = SYS_IOCTL(fd, VIDIOC_DQBUF, buffer);
367 if (ret)
368 return ret;
369
Jeffy Chen1f86bdf2016-08-03 18:20:12 +0800370 rk_vepu_assemble_bitstream(ctx->enc, fd, buffer);
371
Owen Lin133ed582016-08-15 11:47:39 +0800372 assert(!ctx->can_qbuf);
373
374 /* Get the encoder configuration and update the library. */
375 memset(ctx->get_param_payload, 0, ctx->get_param_payload_size);
376 memset(&v4l2_ctrl, 0, sizeof(v4l2_ctrl));
377 v4l2_ctrl.id = V4L2_CID_PRIVATE_ROCKCHIP_GET_PARAMS;
378 v4l2_ctrl.size = ctx->get_param_payload_size;
379 v4l2_ctrl.ptr = ctx->get_param_payload;
380 memset(&ext_ctrls, 0, sizeof(ext_ctrls));
381 /* TODO: change this to config_store after the header is updated. */
382 ext_ctrls.ctrl_class = 0;
383 ext_ctrls.count = 1;
384 ext_ctrls.controls = &v4l2_ctrl;
385 ret = SYS_IOCTL(fd, VIDIOC_G_EXT_CTRLS, &ext_ctrls);
386 if (ret)
387 return ret;
388 bytesused = V4L2_TYPE_IS_MULTIPLANAR(buffer->type) ?
389 buffer->m.planes[0].bytesused : buffer->bytesused;
390
391 if (rk_vepu_update_config(ctx->enc, v4l2_ctrl.ptr, v4l2_ctrl.size,
392 bytesused)) {
393 VLOG_FD(0, "rk_vepu_update_config failed.");
394 return -EIO;
395 }
396 ctx->can_qbuf = true;
397 return qbuf_if_pending_buffer_exists_locked(ctx, fd);
398}
399
400static int ioctl_s_ext_ctrls_locked(struct encoder_context *ctx, int fd,
401 struct v4l2_ext_controls *ext_ctrls)
402{
403 size_t i;
404 struct rk_vepu_runtime_param *runtime_param_ptr;
405
406 bool no_pending_buffer = queue_empty(&ctx->pending_buffers);
407 /*
408 * If buffer queue is empty, update parameters directly.
409 * If buffer queue is not empty, save parameters to the last buffer. And
410 * these values will be sent again when the buffer is ready to deliver.
411 */
412 if (!no_pending_buffer) {
413 struct pending_buffer *element = queue_back(&ctx->pending_buffers);
414 runtime_param_ptr = &element->next_runtime_param;
415 } else {
416 runtime_param_ptr = &ctx->runtime_param;
417 }
418
419 /*
420 * Check each extension control to update keyframe and bitrate
421 * parameters.
422 */
423 for (i = 0; i < ext_ctrls->count; i++) {
424 switch (ext_ctrls->controls[i].id) {
425 case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME:
426 runtime_param_ptr->keyframe_request = true;
427 break;
428 case V4L2_CID_MPEG_VIDEO_BITRATE:
429 runtime_param_ptr->bitrate = ext_ctrls->controls[i].value;
430 break;
Jeffy Chen1f86bdf2016-08-03 18:20:12 +0800431 case V4L2_CID_MPEG_VIDEO_H264_SPS_PPS_BEFORE_IDR:
432 ctx->init_param.h264e.h264_sps_pps_before_idr =
433 ext_ctrls->controls[i].value;
Owen Lin133ed582016-08-15 11:47:39 +0800434 default:
435 break;
436 }
437 }
438
439 if (no_pending_buffer && ctx->enc) {
440 if (rk_vepu_update_param(ctx->enc, runtime_param_ptr)) {
441 VLOG_FD(0, "rk_vepu_update_param failed.");
442 return -EIO;
443 }
444 memset(runtime_param_ptr, 0, sizeof(*runtime_param_ptr));
445 }
446 /* Driver should ignore keyframe and bitrate controls */
447 return SYS_IOCTL(fd, VIDIOC_S_EXT_CTRLS, ext_ctrls);
448}
449
450static int ioctl_s_parm_locked(struct encoder_context *ctx, int fd,
451 struct v4l2_streamparm *parms)
452{
453 if (V4L2_TYPE_IS_OUTPUT(parms->type)
454 && parms->parm.output.timeperframe.denominator) {
455 struct rk_vepu_runtime_param *runtime_param_ptr;
456 bool no_pending_buffer = queue_empty(&ctx->pending_buffers);
457 struct pending_buffer *element = queue_back(&ctx->pending_buffers);
458
459 runtime_param_ptr = no_pending_buffer ? &ctx->runtime_param :
460 &element->next_runtime_param;
461 runtime_param_ptr->framerate_numer =
462 parms->parm.output.timeperframe.denominator;
463 runtime_param_ptr->framerate_denom =
464 parms->parm.output.timeperframe.numerator;
465
466 if (!no_pending_buffer || !ctx->enc)
467 return 0;
468 if (rk_vepu_update_param(ctx->enc, runtime_param_ptr)) {
469 VLOG_FD(0, "rk_vepu_update_param failed.");
470 return -EIO;
471 }
472 memset(runtime_param_ptr, 0, sizeof(*runtime_param_ptr));
473 return 0;
474 }
475 return SYS_IOCTL(fd, VIDIOC_S_PARM, parms);
476}
477
478static int ioctl_reqbufs_locked(struct encoder_context *ctx, int fd,
479 struct v4l2_requestbuffers *reqbufs)
480{
481 int ret = SYS_IOCTL(fd, VIDIOC_REQBUFS, reqbufs);
482 if (ret)
483 return ret;
484 queue_init(&ctx->pending_buffers);
485 return 0;
486}
487
488bool is_rockchip_encoder(int fd) {
489 struct v4l2_capability cap;
490 memset(&cap, 0, sizeof(cap));
491 int ret = SYS_IOCTL(fd, VIDIOC_QUERYCAP, &cap);
492 if (ret)
493 return false;
Pawel Osciake79d5092016-09-06 14:12:41 +0900494 VLOG_FD(1, "driver name return %s\n", (char*)cap.card);
Owen Lin133ed582016-08-15 11:47:39 +0800495 return strstr((const char *)cap.card, "-enc") != NULL;
496}
497
498int set_encoder_config_locked(struct encoder_context *ctx, int fd,
499 uint32_t buffer_index, size_t num_ctrls, uint32_t ctrl_ids[],
500 void **payloads, uint32_t payload_sizes[])
501{
502 size_t i;
503 struct v4l2_ext_controls ext_ctrls;
504
505 if (num_ctrls <= 0)
506 return 0;
507
508 assert(num_ctrls <= MAX_NUM_GET_CONFIG_CTRLS);
509 if (num_ctrls > MAX_NUM_GET_CONFIG_CTRLS) {
510 VLOG_FD(0, "The number of controls exceeds limit.");
511 return -EIO;
512 }
513 memset(&ext_ctrls, 0, sizeof(ext_ctrls));
514 ext_ctrls.config_store = buffer_index + 1;
515 ext_ctrls.count = num_ctrls;
516 ext_ctrls.controls = ctx->v4l2_ctrls;
517 memset(ctx->v4l2_ctrls, 0, sizeof(ctx->v4l2_ctrls));
518 for (i = 0; i < num_ctrls; ++i) {
519 ctx->v4l2_ctrls[i].id = ctrl_ids[i];
520 ctx->v4l2_ctrls[i].ptr = payloads[i];
521 ctx->v4l2_ctrls[i].size = payload_sizes[i];
522 }
523 int ret = SYS_IOCTL(fd, VIDIOC_S_EXT_CTRLS, &ext_ctrls);
524 if (ret) {
525 return ret;
526 }
527 return 0;
528}
529
530static int qbuf_if_pending_buffer_exists_locked(struct encoder_context *ctx,
531 int fd)
532{
533 if (!queue_empty(&ctx->pending_buffers)) {
534 int ret;
535 struct pending_buffer *element = queue_front(&ctx->pending_buffers);
536 VLOG_FD(1, "QBUF a buffer (%d) from the pending queue.",
537 element->buffer.index);
538 if (rk_vepu_update_param(ctx->enc, &element->next_runtime_param)) {
539 VLOG_FD(0, "rk_vepu_update_param failed.");
540 return -EIO;
541 }
542 memset(&element->next_runtime_param, 0,
543 sizeof(element->next_runtime_param));
544 ret = ioctl_qbuf_locked(ctx, fd, &element->buffer);
545 if (ret)
546 return ret;
547 queue_pop_front(&ctx->pending_buffers);
548 }
549 return 0;
550}
551
552static int initialize_libvpu(struct encoder_context *ctx, int fd)
553{
554 struct rk_vepu_init_param init_param;
555 memset(&init_param, 0, sizeof(init_param));
556
557 /* Get the input format. */
558 struct v4l2_format format;
559 memset(&format, 0, sizeof(format));
560 format.type = ctx->output_streamon_type;
561 int ret = SYS_IOCTL(fd, VIDIOC_G_FMT, &format);
562 if (ret)
563 return ret;
564 init_param.input_format = format.fmt.pix_mp.pixelformat;
565
566 /* Get the output format. */
567 memset(&format, 0, sizeof(format));
568 format.type = ctx->capture_streamon_type;
569 ret = SYS_IOCTL(fd, VIDIOC_G_FMT, &format);
570 if (ret)
571 return ret;
572 init_param.output_format = format.fmt.pix_mp.pixelformat;
573
574 /* Get the cropped size. */
575 struct v4l2_crop crop;
576 memset(&crop, 0, sizeof(crop));
577 crop.type = ctx->output_streamon_type;
578 ret = SYS_IOCTL(fd, VIDIOC_G_CROP, &crop);
579 if (ret)
580 return ret;
581 init_param.width = crop.c.width;
582 init_param.height = crop.c.height;
583
Jeffy Chen1f86bdf2016-08-03 18:20:12 +0800584 init_param.h264e = ctx->init_param.h264e;
585
Owen Lin133ed582016-08-15 11:47:39 +0800586 /*
587 * If the encoder library has initialized and parameters have not
588 * changed, skip the initialization.
589 */
590 if (ctx->enc && memcmp(&init_param, &ctx->init_param, sizeof(init_param))) {
591 rk_vepu_deinit(ctx->enc);
592 ctx->enc = NULL;
593 }
594 if (!ctx->enc) {
595 memcpy(&ctx->init_param, &init_param, sizeof(init_param));
596 ctx->enc = rk_vepu_init(&init_param);
597 if (ctx->enc == NULL) {
598 VLOG_FD(0, "Failed to initialize encoder library.");
599 return -EIO;
600 }
601 }
602 if (rk_vepu_update_param(ctx->enc, &ctx->runtime_param)) {
603 VLOG_FD(0, "rk_vepu_update_param failed.");
604 return -EIO;
605 }
606 memset(&ctx->runtime_param, 0, sizeof(struct rk_vepu_runtime_param));
607 return 0;
608}
609
610static void queue_init(struct pending_buffer_queue *queue)
611{
612 memset(queue, 0, sizeof(struct pending_buffer_queue));
613}
614
615static bool queue_empty(struct pending_buffer_queue *queue)
616{
617 return queue->count == 0;
618}
619
620static bool queue_full(struct pending_buffer_queue *queue)
621{
622 return queue->count == PENDING_BUFFER_QUEUE_SIZE;
623}
624
625static int queue_push_back(struct pending_buffer_queue *queue,
626 struct v4l2_buffer *buffer)
627{
628 if (queue_full(queue))
629 return -ENOMEM;
630 int rear = (queue->front + queue->count) % PENDING_BUFFER_QUEUE_SIZE;
631 queue->count++;
632 struct pending_buffer *entry = &queue->buf_array[rear];
633 memset(entry, 0, sizeof(*entry));
634
635 entry->buffer = *buffer;
636 if (V4L2_TYPE_IS_MULTIPLANAR(buffer->type)) {
637 memcpy(entry->planes, buffer->m.planes,
638 sizeof(struct v4l2_plane) * buffer->length);
639 entry->buffer.m.planes = entry->planes;
640 }
641 return 0;
642}
643
644static void queue_pop_front(struct pending_buffer_queue *queue)
645{
646 assert(!queue_empty(queue));
647 queue->count--;
648 queue->front = (queue->front + 1) % PENDING_BUFFER_QUEUE_SIZE;
649}
650
651static struct pending_buffer *queue_front(struct pending_buffer_queue *queue)
652{
653 if (queue_empty(queue))
654 return NULL;
655 return &queue->buf_array[queue->front];
656}
657
658static struct pending_buffer *queue_back(struct pending_buffer_queue *queue)
659{
660 if (queue_empty(queue))
661 return NULL;
662 return &queue->buf_array[(queue->front + queue->count - 1) %
663 PENDING_BUFFER_QUEUE_SIZE];
664}
665
666static void get_log_level()
667{
668 char *log_level_str = getenv("LIBV4L_PLUGIN_LOG_LEVEL");
669 if (log_level_str != NULL)
670 g_log_level = strtol(log_level_str, NULL, 10);
671}
672
673static const char* v4l_cmd2str(unsigned long int cmd)
674{
675 switch (cmd) {
676 case VIDIOC_QUERYCAP:
677 return "VIDIOC_QUERYCAP";
678 case VIDIOC_TRY_FMT:
679 return "VIDIOC_TRY_FMT";
680 case VIDIOC_S_FMT:
681 return "VIDIOC_S_FMT";
682 case VIDIOC_G_FMT:
683 return "VIDIOC_G_FMT";
684 case VIDIOC_ENUM_FMT:
685 return "VIDIOC_ENUM_FMT";
686 case VIDIOC_S_PARM:
687 return "VIDIOC_S_PARM";
688 case VIDIOC_G_PARM:
689 return "VIDIOC_G_PARM";
690 case VIDIOC_QBUF:
691 return "VIDIOC_QBUF";
692 case VIDIOC_DQBUF:
693 return "VIDIOC_DQBUF";
694 case VIDIOC_PREPARE_BUF:
695 return "VIDIOC_PREPARE_BUF";
696 case VIDIOC_CREATE_BUFS:
697 return "VIDIOC_CREATE_BUFS";
698 case VIDIOC_REQBUFS:
699 return "VIDIOC_REQBUFS";
700 case VIDIOC_STREAMON:
701 return "VIDIOC_STREAMON";
702 case VIDIOC_STREAMOFF:
703 return "VIDIOC_STREAMOFF";
704 case VIDIOC_S_CROP:
705 return "VIDIOC_S_CROP";
706 case VIDIOC_S_CTRL:
707 return "VIDIOC_S_CTRL";
708 case VIDIOC_G_EXT_CTRLS:
709 return "VIDIOC_G_EXT_CTRLS";
710 case VIDIOC_S_EXT_CTRLS:
711 return "VIDIOC_S_EXT_CTRLS";
712 case VIDIOC_QUERYBUF:
713 return "VIDIOC_QUERYBUF";
714 default:
715 return "UNKNOWN";
716 }
717}
718
719PLUGIN_PUBLIC const struct libv4l_dev_ops libv4l2_plugin = {
720 .init = &plugin_init,
721 .close = &plugin_close,
722 .ioctl = &plugin_ioctl,
723};