2 Copyright (c) 2012, Broadcom Europe Ltd
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of the copyright holder nor the
13 names of its contributors may be used to endorse or promote products
14 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include "interface/mmal/mmal.h"
37 #include "interface/mmal/mmal_logging.h"
38 #include "interface/mmal/util/mmal_util.h"
39 #include "interface/mmal/util/mmal_default_components.h"
41 #define USE_CONTAINER 0
44 #include "containers/containers.h"
45 #include "containers/core/containers_utils.h" // FIXME
46 #include "containers/containers_codecs.h"
49 /** Number of buffers we want to use for video render. Video render needs at least 2. */
50 #define VIDEO_OUTPUT_BUFFERS_NUM 3
52 /** After this many packets, the container (if any) will be closed and we
53 * start discarding encoded packets.
55 #define MAX_PACKET_COUNT 150
57 /** Initialise a parameter structure */
58 #define INIT_PARAMETER(PARAM, PARAM_ID) \
60 memset(&(PARAM), 0, sizeof(PARAM)); \
61 (PARAM).hdr.id = PARAM_ID; \
62 (PARAM).hdr.size = sizeof(PARAM); \
65 /* Utility functions to manipulate containers */
67 static VC_CONTAINER_T *test_container_open(const char *uri, MMAL_ES_FORMAT_T* format, MMAL_STATUS_T *status);
68 static MMAL_STATUS_T test_container_write(VC_CONTAINER_T *container, MMAL_BUFFER_HEADER_T *buffer);
69 static VC_CONTAINER_FOURCC_T test_container_encoding_to_codec(uint32_t encoding);
72 /* Utility function to create and setup the camera viewfinder component */
73 static MMAL_COMPONENT_T *test_camera_create(MMALCAM_BEHAVIOUR_T *behaviour, MMAL_STATUS_T *status);
74 static MMAL_BOOL_T mmalcam_next_effect(MMAL_COMPONENT_T *camera);
75 static MMAL_BOOL_T mmalcam_next_rotation(MMAL_COMPONENT_T *camera);
76 static MMAL_BOOL_T mmalcam_next_zoom(MMAL_COMPONENT_T *camera);
77 static MMAL_BOOL_T mmalcam_next_focus(MMAL_COMPONENT_T *camera);
78 static MMAL_BOOL_T mmalcam_reset_focus(MMAL_COMPONENT_T *camera, MMAL_PARAM_FOCUS_T focus_setting);
79 static MMAL_BOOL_T mmalcam_next_drc(MMAL_COMPONENT_T *camera);
80 static MMAL_BOOL_T mmalcam_next_hdr(MMAL_COMPONENT_T *camera);
81 static MMAL_BOOL_T mmalcam_next_colour_param(MMAL_COMPONENT_T *camera, uint32_t id, int min, int max, const char *param_name);
83 /* Utility function to create and setup the video render component */
84 static MMAL_COMPONENT_T *test_video_render_create(MMALCAM_BEHAVIOUR_T *behaviour, MMAL_STATUS_T *status);
86 /* Utility function to create and setup the video encoder component */
87 static MMAL_COMPONENT_T *test_video_encoder_create(MMALCAM_BEHAVIOUR_T *behaviour, MMAL_STATUS_T *status);
89 /*****************************************************************************/
92 MMAL_CAM_BUFFER_READY = 1 << 0,
93 MMAL_CAM_AUTOFOCUS_COMPLETE = 1 << 1,
94 MMAL_CAM_ANY_EVENT = 0x7FFFFFFF
97 static VCOS_EVENT_FLAGS_T events;
98 VCOS_LOG_CAT_T mmalcam_log_category;
99 static MMAL_BOOL_T zero_copy;
100 static MMAL_BOOL_T tunneling;
102 static MMAL_BOOL_T enable_zero_copy(void)
107 static MMAL_BOOL_T enable_tunneling(void)
112 /* Buffer header callbacks */
113 static void control_bh_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
115 LOG_DEBUG("control_bh_cb %p,%p (cmd=0x%08x)", port, buffer, buffer->cmd);
116 if (buffer->cmd == MMAL_EVENT_PARAMETER_CHANGED)
118 MMAL_EVENT_PARAMETER_CHANGED_T *param = (MMAL_EVENT_PARAMETER_CHANGED_T *)buffer->data;
120 vcos_assert(buffer->length >= sizeof(MMAL_EVENT_PARAMETER_CHANGED_T));
121 vcos_assert(buffer->length == param->hdr.size);
122 switch (param->hdr.id)
124 case MMAL_PARAMETER_FOCUS_STATUS:
125 vcos_assert(param->hdr.size == sizeof(MMAL_PARAMETER_FOCUS_STATUS_T));
127 MMAL_PARAMETER_FOCUS_STATUS_T *focus_status = (MMAL_PARAMETER_FOCUS_STATUS_T *)param;
128 LOG_INFO("Focus status: %d", focus_status->status);
129 vcos_event_flags_set(&events, MMAL_CAM_AUTOFOCUS_COMPLETE, VCOS_OR);
132 case MMAL_PARAMETER_CAMERA_NUM:
133 vcos_assert(param->hdr.size == sizeof(MMAL_PARAMETER_UINT32_T));
135 MMAL_PARAMETER_UINT32_T *camera_num = (MMAL_PARAMETER_UINT32_T *)param;
136 LOG_INFO("Camera number: %d", camera_num->value);
140 LOG_ERROR("Unexpected changed event for parameter 0x%08x", param->hdr.id);
145 LOG_ERROR("Unexpected event, 0x%08x", buffer->cmd);
147 mmal_buffer_header_release(buffer);
150 static void generic_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
152 if (buffer->cmd != 0)
154 LOG_INFO("%s callback: event %u not supported", port->name, buffer->cmd);
155 mmal_buffer_header_release(buffer);
159 MMAL_QUEUE_T *queue = (MMAL_QUEUE_T *)port->userdata;
161 LOG_DEBUG("%s callback", port->name);
162 mmal_queue_put(queue, buffer);
165 vcos_event_flags_set(&events, MMAL_CAM_BUFFER_READY, VCOS_OR);
168 static void generic_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
170 if (buffer->cmd != 0)
172 LOG_INFO("%s callback: event %u not supported", port->name, buffer->cmd);
175 mmal_buffer_header_release(buffer);
176 vcos_event_flags_set(&events, MMAL_CAM_BUFFER_READY, VCOS_OR);
179 static MMAL_STATUS_T setup_output_port(MMAL_PORT_T *output_port, MMAL_QUEUE_T **p_queue, MMAL_POOL_T **p_pool)
181 MMAL_STATUS_T status = MMAL_ENOMEM;
182 MMAL_QUEUE_T *queue = NULL;
183 MMAL_POOL_T *pool = NULL;
185 /* Create a queue for frames filled by the output port.
186 * The main loop will pass these on to the input port. */
187 queue = mmal_queue_create();
190 LOG_ERROR("failed to create queue for %s", output_port->name);
194 /* Create pool of buffer headers for the output port to consume */
195 pool = mmal_port_pool_create(output_port, output_port->buffer_num, output_port->buffer_size);
198 LOG_ERROR("failed to create pool for %s", output_port->name);
202 output_port->userdata = (void *)queue;
204 status = mmal_port_enable(output_port, generic_output_port_cb);
205 if (status != MMAL_SUCCESS)
207 LOG_ERROR("failed to enable %s", output_port->name);
218 mmal_queue_destroy(queue);
220 mmal_pool_destroy(pool);
225 static MMAL_STATUS_T connect_ports(MMAL_PORT_T *output_port, MMAL_PORT_T *input_port, MMAL_QUEUE_T **p_queue, MMAL_POOL_T **p_pool)
227 MMAL_STATUS_T status;
229 status = mmal_format_full_copy(input_port->format, output_port->format);
230 if (status != MMAL_SUCCESS)
233 status = mmal_port_format_commit(input_port);
234 if (status != MMAL_SUCCESS)
237 if (enable_tunneling())
239 status = mmal_port_connect(output_port, input_port);
240 if (status != MMAL_SUCCESS)
243 status = mmal_port_enable(output_port, NULL);
244 if (status != MMAL_SUCCESS)
245 mmal_port_disconnect(output_port);
250 /* Non-tunneling setup */
251 input_port->buffer_size = input_port->buffer_size_recommended;
252 if (input_port->buffer_size < input_port->buffer_size_min)
253 input_port->buffer_size = input_port->buffer_size_min;
254 input_port->buffer_num = input_port->buffer_num_recommended;
255 if (input_port->buffer_num < input_port->buffer_num_min)
256 input_port->buffer_num = input_port->buffer_num_min;
257 output_port->buffer_size = output_port->buffer_size_recommended;
258 if (output_port->buffer_size < output_port->buffer_size_min)
259 output_port->buffer_size = output_port->buffer_size_min;
260 output_port->buffer_num = output_port->buffer_num_recommended;
261 if (output_port->buffer_num < output_port->buffer_num_min)
262 output_port->buffer_num = output_port->buffer_num_min;
264 input_port->buffer_num = output_port->buffer_num =
265 MMAL_MAX(input_port->buffer_num, output_port->buffer_num);
266 input_port->buffer_size = output_port->buffer_size =
267 MMAL_MAX(input_port->buffer_size, output_port->buffer_size);
269 status = setup_output_port(output_port, p_queue, p_pool);
270 if (status != MMAL_SUCCESS)
273 status = mmal_port_enable(input_port, generic_input_port_cb);
274 if (status != MMAL_SUCCESS)
280 if (input_port->is_enabled)
281 mmal_port_disable(input_port);
282 if (output_port->is_enabled)
283 mmal_port_disable(output_port);
285 mmal_pool_destroy(*p_pool);
287 mmal_queue_destroy(*p_queue);
292 static MMAL_STATUS_T send_buffer_from_queue(MMAL_PORT_T *port, MMAL_QUEUE_T *queue)
294 MMAL_STATUS_T status = MMAL_SUCCESS;
295 MMAL_BUFFER_HEADER_T *buffer;
300 buffer = mmal_queue_get(queue);
304 status = mmal_port_send_buffer(port, buffer);
306 if (status != MMAL_SUCCESS)
308 mmal_queue_put_back(queue, buffer);
309 LOG_DEBUG("%s send failed (%i)", port->name, status);
316 static MMAL_STATUS_T fill_port_from_pool(MMAL_PORT_T *port, MMAL_POOL_T *pool)
318 MMAL_STATUS_T status = MMAL_SUCCESS;
325 while (status == MMAL_SUCCESS && mmal_queue_length(queue) > 0)
326 status = send_buffer_from_queue(port, queue);
331 static void disable_port(MMAL_PORT_T *port)
333 if (port && port->is_enabled)
334 mmal_port_disable(port);
338 static int parse_vformat(const char* vformat, uint32_t *out_width,
339 uint32_t *out_height, uint32_t *out_encoding)
342 uint32_t width, height, encoding;
344 // coverity[secure_coding] Scanning integer values, and a string where the length is safe given vcodec declaration
345 if (sscanf(vformat, "%4ux%4u:%7s", &width, &height, vcodec) != 3)
347 fprintf(stderr, "Error, malformed or unsupported video format: %s\n", vformat);
351 if (!vcos_strncasecmp(vcodec, "h263", 4))
353 encoding = MMAL_ENCODING_H263;
354 /* Special case, H263 supports a limited set of resolutions */
355 if (!((width == 128 && height == 96) ||
356 (width == 176 && height == 144) ||
357 (width == 352 && height == 288) ||
358 (width == 704 && height == 576) ||
359 (width == 1408 && height == 1152)))
362 "Error, only 128x96, 176x144, 352x288, 704x576 and 1408x1152 are supported for H263\n");
366 else if (!vcos_strncasecmp(vcodec, "mp4v", 4))
367 encoding = MMAL_ENCODING_MP4V;
368 else if (!vcos_strncasecmp(vcodec, "h264", 4))
369 encoding = MMAL_ENCODING_H264;
370 else if (!vcos_strncasecmp(vcodec, "jpeg", 4))
371 encoding = MMAL_ENCODING_JPEG;
374 fprintf(stderr, "Error, unknown video encoding: %s\n", vcodec);
381 *out_height = height;
383 *out_encoding = encoding;
384 LOG_DEBUG("Video format: w:%d h:%d codec:%4.4s", width, height, (const char *)&encoding);
389 /*****************************************************************************/
390 int test_mmal_start_camcorder(volatile int *stop, MMALCAM_BEHAVIOUR_T *behaviour)
392 MMAL_STATUS_T status = MMAL_SUCCESS;
393 MMAL_POOL_T *pool_viewfinder = 0, *pool_encoder_in = 0, *pool_encoder_out = 0;
394 MMAL_QUEUE_T *queue_viewfinder = 0, *queue_encoder_in = 0, *queue_encoder_out = 0;
395 MMAL_COMPONENT_T *camera = 0, *encoder = 0, *render = 0;
396 MMAL_PORT_T *viewfinder_port = 0, *video_port = 0, *still_port = 0;
397 MMAL_PORT_T *render_port = 0, *encoder_input = 0, *encoder_output = 0;
398 uint32_t ms_per_change, last_change_ms, set_focus_delay_ms;
399 int packet_count = 0;
401 VC_CONTAINER_T *container = 0;
405 if(vcos_event_flags_create(&events, "MMALCam") != VCOS_SUCCESS)
407 behaviour->init_result = MMALCAM_INIT_ERROR_EVENT_FLAGS;
411 zero_copy = behaviour->zero_copy;
412 tunneling = behaviour->tunneling;
414 /* Create and setup camera viewfinder component */
415 camera = test_camera_create(behaviour, &status);
418 behaviour->init_result = MMALCAM_INIT_ERROR_CAMERA;
421 viewfinder_port = camera->output[0];
422 video_port = camera->output[1];
423 still_port = camera->output[2];
425 /* Create and setup video render component */
426 render = test_video_render_create(behaviour, &status);
429 behaviour->init_result = MMALCAM_INIT_ERROR_RENDER;
432 render_port = render->input[0];
434 status = connect_ports(viewfinder_port, render_port, &queue_viewfinder, &pool_viewfinder);
435 if (status != MMAL_SUCCESS)
437 behaviour->init_result = MMALCAM_INIT_ERROR_VIEWFINDER;
443 MMAL_PARAMETER_BOOLEAN_T camera_capture =
444 {{MMAL_PARAMETER_CAPTURE, sizeof(MMAL_PARAMETER_BOOLEAN_T)}, 1};
446 /* Create and setup video encoder component */
447 encoder = test_video_encoder_create(behaviour, &status);
450 behaviour->init_result = MMALCAM_INIT_ERROR_ENCODER;
453 encoder_input = encoder->input[0];
454 encoder_output = encoder->output[0];
456 if (encoder_output->format->encoding == MMAL_ENCODING_JPEG)
457 video_port = still_port;
459 status = connect_ports(video_port, encoder_input, &queue_encoder_in, &pool_encoder_in);
460 if (status != MMAL_SUCCESS)
462 behaviour->init_result = MMALCAM_INIT_ERROR_ENCODER_IN;
466 status = setup_output_port(encoder_output, &queue_encoder_out, &pool_encoder_out);
467 if (status != MMAL_SUCCESS)
469 behaviour->init_result = MMALCAM_INIT_ERROR_ENCODER_OUT;
473 status = mmal_port_parameter_set(video_port, &camera_capture.hdr);
474 if (status != MMAL_SUCCESS && status != MMAL_ENOSYS)
476 behaviour->init_result = MMALCAM_INIT_ERROR_CAMERA_CAPTURE;
481 container = test_container_open(behaviour->uri, encoder_output->format, &status);
484 /* Notify user, carry on discarding encoded output buffers */
485 fprintf(stderr, "Error (%i) opening container: %s\n", status, behaviour->uri);
489 output = fopen(behaviour->uri, "wb");
492 /* Notify user, carry on discarding encoded output buffers */
493 fprintf(stderr, "Error opening output file: %s\n", behaviour->uri);
498 /* Initialisation now complete */
499 behaviour->init_result = MMALCAM_INIT_SUCCESS;
500 vcos_semaphore_post(&behaviour->init_sem);
502 ms_per_change = behaviour->seconds_per_change * 1000;
503 last_change_ms = vcos_get_ms();
504 set_focus_delay_ms = 1000;
508 MMAL_BUFFER_HEADER_T *buffer;
511 vcos_event_flags_get(&events, MMAL_CAM_ANY_EVENT, VCOS_OR_CONSUME, VCOS_TICKS_TO_MS(2), &set);
514 if (behaviour->focus_test != MMAL_PARAM_FOCUS_MAX)
516 if (set & MMAL_CAM_AUTOFOCUS_COMPLETE ||
517 (set_focus_delay_ms && (vcos_get_ms() - last_change_ms) >= set_focus_delay_ms))
519 set_focus_delay_ms = 0;
520 mmalcam_reset_focus(camera, behaviour->focus_test);
524 /* Send empty buffers to the output ports */
525 status = fill_port_from_pool(viewfinder_port, pool_viewfinder);
526 if (status != MMAL_SUCCESS)
528 status = fill_port_from_pool(video_port, pool_encoder_in);
529 if (status != MMAL_SUCCESS)
531 status = fill_port_from_pool(encoder_output, pool_encoder_out);
532 if (status != MMAL_SUCCESS)
535 /* Process filled output buffers */
536 status = send_buffer_from_queue(render_port, queue_viewfinder);
537 if (status != MMAL_SUCCESS)
539 status = send_buffer_from_queue(encoder_input, queue_encoder_in);
540 if (status != MMAL_SUCCESS)
543 /* Process output buffers from encoder */
544 if (queue_encoder_out)
546 buffer = mmal_queue_get(queue_encoder_out);
555 mmal_buffer_header_mem_lock(buffer);
557 test_container_write(container, buffer);
559 LOG_ERROR("Write %d bytes of data from %p", buffer->length, buffer->data);
560 fwrite(buffer->data, 1, buffer->length, output);
562 mmal_buffer_header_mem_unlock(buffer);
564 if (packet_count > MAX_PACKET_COUNT)
567 vc_container_close(container);
573 fprintf(stderr, "All packets written\n");
576 mmal_buffer_header_release(buffer);
580 /* Change a camera parameter if requested */
581 if (ms_per_change != 0)
583 if((vcos_get_ms() - last_change_ms) >= ms_per_change)
585 last_change_ms = vcos_get_ms();
586 switch (behaviour->change)
588 case MMALCAM_CHANGE_IMAGE_EFFECT:
589 if (!mmalcam_next_effect(camera))
592 case MMALCAM_CHANGE_ROTATION:
593 if (!mmalcam_next_rotation(camera))
596 case MMALCAM_CHANGE_ZOOM:
597 if (!mmalcam_next_zoom(camera))
600 case MMALCAM_CHANGE_FOCUS:
601 if (!mmalcam_next_focus(camera))
604 case MMALCAM_CHANGE_DRC:
605 if (!mmalcam_next_drc(camera))
608 case MMALCAM_CHANGE_HDR:
609 if (!mmalcam_next_hdr(camera))
612 case MMALCAM_CHANGE_CONTRAST:
613 if (!mmalcam_next_colour_param(camera, MMAL_PARAMETER_CONTRAST, -100, 100, "contrast"))
616 case MMALCAM_CHANGE_BRIGHTNESS:
617 if (!mmalcam_next_colour_param(camera, MMAL_PARAMETER_BRIGHTNESS, 0, 100, "brightness"))
620 case MMALCAM_CHANGE_SATURATION:
621 if (!mmalcam_next_colour_param(camera, MMAL_PARAMETER_SATURATION, -100, 100, "saturation"))
624 case MMALCAM_CHANGE_SHARPNESS:
625 if (!mmalcam_next_colour_param(camera, MMAL_PARAMETER_SHARPNESS, -100, 100, "sharpness"))
629 LOG_ERROR("Unexpected change behaviour: %d", behaviour->change);
637 disable_port(viewfinder_port);
638 disable_port(render_port);
639 disable_port(video_port);
640 disable_port(encoder_input);
641 disable_port(encoder_output);
643 /* Disable components */
644 mmal_component_disable(render);
646 mmal_component_disable(encoder);
647 mmal_component_disable(camera);
649 INIT_PARAMETER(behaviour->render_stats, MMAL_PARAMETER_STATISTICS);
650 mmal_port_parameter_get(render_port, &behaviour->render_stats.hdr);
653 INIT_PARAMETER(behaviour->encoder_stats, MMAL_PARAMETER_STATISTICS);
654 mmal_port_parameter_get(encoder_output, &behaviour->encoder_stats.hdr);
658 /* The pools need to be destroyed first since they are owned by the components */
660 mmal_port_pool_destroy(viewfinder_port, pool_viewfinder);
662 mmal_port_pool_destroy(video_port, pool_encoder_in);
664 mmal_port_pool_destroy(encoder_output, pool_encoder_out);
667 mmal_component_destroy(render);
669 mmal_component_destroy(encoder);
671 mmal_component_destroy(camera);
674 mmal_queue_destroy(queue_viewfinder);
676 mmal_queue_destroy(queue_encoder_in);
677 if(queue_encoder_out)
678 mmal_queue_destroy(queue_encoder_out);
682 vc_container_close(container);
687 vcos_event_flags_delete(&events);
690 printf("Packet count: %d\n", packet_count);
692 if (behaviour->init_result != MMALCAM_INIT_SUCCESS)
693 vcos_semaphore_post(&behaviour->init_sem);
698 /*****************************************************************************/
699 static MMAL_COMPONENT_T *test_camera_create(MMALCAM_BEHAVIOUR_T *behaviour, MMAL_STATUS_T *status)
701 MMAL_COMPONENT_T *camera = 0;
702 MMAL_ES_FORMAT_T *format;
703 MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T change_event_request =
704 {{MMAL_PARAMETER_CHANGE_EVENT_REQUEST, sizeof(MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T)}, 0, 1};
705 MMAL_PORT_T *viewfinder_port = NULL, *video_port = NULL, *still_port = NULL;
706 uint32_t width, height;
707 MMAL_PARAMETER_INT32_T camera_num =
708 {{MMAL_PARAMETER_CAMERA_NUM, sizeof(camera_num)},0};
710 /* Create the component */
711 *status = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &camera);
712 if(*status != MMAL_SUCCESS)
714 LOG_ERROR("couldn't create camera");
717 if(!camera->output_num)
719 LOG_ERROR("camera doesn't have output ports");
720 *status = MMAL_EINVAL;
724 viewfinder_port = camera->output[0];
725 video_port = camera->output[1];
726 still_port = camera->output[2];
728 change_event_request.change_id = MMAL_PARAMETER_FOCUS_STATUS;
729 *status = mmal_port_parameter_set(camera->control, &change_event_request.hdr);
730 if (*status != MMAL_SUCCESS && *status != MMAL_ENOSYS)
732 LOG_ERROR("No focus status change events");
734 camera_num.value = behaviour->camera_num;
735 *status = mmal_port_parameter_set(camera->control, &camera_num.hdr);
736 if (*status != MMAL_SUCCESS && *status != MMAL_ENOSYS)
738 LOG_ERROR("No camera number change events");
740 if (enable_zero_copy())
742 MMAL_PARAMETER_BOOLEAN_T param_zc =
743 {{MMAL_PARAMETER_ZERO_COPY, sizeof(MMAL_PARAMETER_BOOLEAN_T)}, 1};
744 *status = mmal_port_parameter_set(viewfinder_port, ¶m_zc.hdr);
745 if( *status != MMAL_SUCCESS && *status != MMAL_ENOSYS )
747 LOG_ERROR("failed to set zero copy on camera output");
750 LOG_INFO("enabled zero copy on camera");
751 *status = mmal_port_parameter_set(video_port, ¶m_zc.hdr);
752 if( *status != MMAL_SUCCESS && *status != MMAL_ENOSYS )
754 LOG_ERROR("failed to set zero copy on camera output");
757 *status = mmal_port_parameter_set(still_port, ¶m_zc.hdr);
758 if( *status != MMAL_SUCCESS && *status != MMAL_ENOSYS )
760 LOG_ERROR("failed to set zero copy on camera output");
765 if ( behaviour->change == MMALCAM_CHANGE_HDR )
767 MMAL_PARAMETER_ALGORITHM_CONTROL_T algo_ctrl = {{MMAL_PARAMETER_ALGORITHM_CONTROL, sizeof(MMAL_PARAMETER_ALGORITHM_CONTROL_T)},
768 MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_HIGH_DYNAMIC_RANGE, 1 };
769 mmal_port_parameter_set(camera->control, &algo_ctrl.hdr);
772 *status = mmal_port_enable(camera->control, control_bh_cb);
775 LOG_ERROR("control port couldn't be enabled: %d", *status);
779 /* Set camera viewfinder port format */
780 if (parse_vformat(behaviour->vformat, &width, &height, NULL))
782 *status = MMAL_EINVAL;
786 /* Default to integer frame rate in numerator */
787 if (!behaviour->frame_rate.den)
788 behaviour->frame_rate.den = 1;
791 MMAL_PARAMETER_CAMERA_CONFIG_T cam_config = {{MMAL_PARAMETER_CAMERA_CONFIG,sizeof(cam_config)},
792 .max_stills_w = width,
793 .max_stills_h = height,
795 .one_shot_stills = 0,
796 .max_preview_video_w = width,
797 .max_preview_video_h = height,
798 .num_preview_video_frames = 3,
799 .stills_capture_circular_buffer_height = 0,
800 .fast_preview_resume = 0,
801 /* No way of using fast resume in Android, as preview
802 * automatically stops on capture.
804 .use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RESET_STC
807 mmal_port_parameter_set(camera->control, &cam_config.hdr);
810 /* Set up the viewfinder port format */
811 format = viewfinder_port->format;
812 if (behaviour->opaque)
813 format->encoding = MMAL_ENCODING_OPAQUE;
815 format->encoding = MMAL_ENCODING_I420;
817 format->es->video.width = width;
818 format->es->video.height = height;
819 format->es->video.crop.x = 0;
820 format->es->video.crop.y = 0;
821 format->es->video.crop.width = width;
822 format->es->video.crop.height = height;
823 format->es->video.frame_rate = behaviour->frame_rate;
825 *status = mmal_port_format_commit(viewfinder_port);
828 LOG_ERROR("camera viewfinder format couldn't be set");
832 /* Set the same format on the video (for encoder) port */
833 mmal_format_full_copy(video_port->format, format);
834 *status = mmal_port_format_commit(video_port);
837 LOG_ERROR("camera video format couldn't be set");
841 /* Ensure there are enough buffers to avoid dropping frames */
842 if (video_port->buffer_num < VIDEO_OUTPUT_BUFFERS_NUM)
843 video_port->buffer_num = VIDEO_OUTPUT_BUFFERS_NUM;
845 /* Set the same format on the still (for encoder) port */
846 mmal_format_full_copy(still_port->format, format);
847 *status = mmal_port_format_commit(still_port);
850 LOG_ERROR("camera still format couldn't be set");
854 /* Ensure there are enough buffers to avoid dropping frames */
855 if (still_port->buffer_num < VIDEO_OUTPUT_BUFFERS_NUM)
856 still_port->buffer_num = VIDEO_OUTPUT_BUFFERS_NUM;
858 /* Enable component */
859 *status = mmal_component_enable(camera);
862 LOG_ERROR("camera component couldn't be enabled");
869 if(camera) mmal_component_destroy(camera);
873 /*****************************************************************************/
874 static MMAL_BOOL_T mmalcam_next_effect(MMAL_COMPONENT_T *camera)
876 static const MMAL_PARAM_IMAGEFX_T effects[] = {
877 MMAL_PARAM_IMAGEFX_NONE,
878 MMAL_PARAM_IMAGEFX_NEGATIVE,
879 MMAL_PARAM_IMAGEFX_SOLARIZE
881 static unsigned int index;
882 MMAL_PARAMETER_IMAGEFX_T image_fx = {{ MMAL_PARAMETER_IMAGE_EFFECT, sizeof(image_fx)},0};
883 MMAL_PARAMETER_IMAGEFX_T image_fx_check = {{ MMAL_PARAMETER_IMAGE_EFFECT, sizeof(image_fx)},0};
884 MMAL_STATUS_T result;
887 if(index >= countof(effects))
889 image_fx.value = effects[index];
890 result = mmal_port_parameter_set(camera->control, &image_fx.hdr);
891 if (result != MMAL_SUCCESS)
893 LOG_ERROR("Failed to set image effect, %d", result);
896 result = mmal_port_parameter_get(camera->control, &image_fx_check.hdr);
897 if (result != MMAL_SUCCESS)
899 LOG_ERROR("Failed to retrieve image effect, %d", result);
902 if (memcmp(&image_fx, &image_fx_check, sizeof(image_fx)) != 0)
904 LOG_ERROR("Image effect set (%d) was not retrieved (%d)", image_fx.value, image_fx_check.value);
910 /*****************************************************************************/
911 static MMAL_BOOL_T mmalcam_next_rotation(MMAL_COMPONENT_T *camera)
913 static MMAL_PARAMETER_UINT32_T rotate = {{MMAL_PARAMETER_ROTATION,sizeof(rotate)},0};
914 MMAL_PARAMETER_UINT32_T rotate_check = {{MMAL_PARAMETER_ROTATION,sizeof(rotate_check)},0};
915 MMAL_STATUS_T result;
918 if(rotate.value == 360)
920 result = mmal_port_parameter_set(camera->output[0], &rotate.hdr);
921 if (result != MMAL_SUCCESS)
923 LOG_ERROR("Failed to set rotation, %d", result);
926 result = mmal_port_parameter_get(camera->output[0], &rotate_check.hdr);
927 if (result != MMAL_SUCCESS)
929 LOG_ERROR("Failed to retrieve rotation, %d", result);
932 if (memcmp(&rotate, &rotate_check, sizeof(rotate)) != 0)
934 LOG_ERROR("Rotation set (%d) was not retrieved (%d)", rotate.value, rotate_check.value);
940 /*****************************************************************************/
941 static MMAL_BOOL_T mmalcam_next_zoom(MMAL_COMPONENT_T *camera)
943 static MMAL_PARAMETER_SCALEFACTOR_T scale = {{MMAL_PARAMETER_ZOOM,sizeof(scale)},1<<16,1<<16};
944 static int32_t dirn = 1 << 14;
945 MMAL_PARAMETER_SCALEFACTOR_T scale_check = {{MMAL_PARAMETER_ZOOM,sizeof(scale_check)},0,0};
946 MMAL_STATUS_T result;
948 scale.scale_x += dirn;
949 scale.scale_y += dirn;
950 if (scale.scale_x >= 4<<16 || scale.scale_x <= 1<<16)
952 result = mmal_port_parameter_set(camera->control, &scale.hdr);
953 if (result != MMAL_SUCCESS)
955 LOG_ERROR("Failed to set scale, %d", result);
958 result = mmal_port_parameter_get(camera->control, &scale_check.hdr);
959 if (result != MMAL_SUCCESS)
961 LOG_ERROR("Failed to retrieve scale, %d", result);
964 if (memcmp(&scale, &scale_check, sizeof(scale)) != 0)
966 LOG_ERROR("Scale set (%d,%d) was not retrieved (%d,%d)",
967 scale.scale_x, scale.scale_y, scale_check.scale_x, scale_check.scale_y);
973 /*****************************************************************************/
974 static MMAL_BOOL_T mmalcam_next_focus(MMAL_COMPONENT_T *camera)
976 static const MMAL_PARAM_FOCUS_T focus_setting[] = {
977 MMAL_PARAM_FOCUS_AUTO,
978 MMAL_PARAM_FOCUS_AUTO_MACRO,
979 MMAL_PARAM_FOCUS_CAF,
980 MMAL_PARAM_FOCUS_FIXED_INFINITY,
981 MMAL_PARAM_FOCUS_FIXED_HYPERFOCAL,
982 MMAL_PARAM_FOCUS_FIXED_MACRO,
983 MMAL_PARAM_FOCUS_EDOF,
985 static unsigned int index;
986 static MMAL_PARAMETER_FOCUS_T focus = {{MMAL_PARAMETER_FOCUS,sizeof(focus)},0};
987 static MMAL_PARAMETER_FOCUS_T focus_check = {{MMAL_PARAMETER_FOCUS,sizeof(focus)},0};
988 MMAL_STATUS_T result;
991 if(index >= countof(focus_setting))
993 focus.value = focus_setting[index];
994 result = mmal_port_parameter_set(camera->control, &focus.hdr);
995 if (result != MMAL_SUCCESS)
997 LOG_ERROR("Failed to set focus to %d", focus.value);
998 /* As this depends on the camera module, do not fail */
1001 result = mmal_port_parameter_get(camera->control, &focus_check.hdr);
1002 if (result != MMAL_SUCCESS)
1004 LOG_ERROR("Failed to retrieve focus, %d", result);
1007 /* Focus setting is asynchronous, so the value read back may not match what was set */
1011 /*****************************************************************************/
1012 static MMAL_BOOL_T mmalcam_reset_focus(MMAL_COMPONENT_T *camera, MMAL_PARAM_FOCUS_T focus_setting)
1014 MMAL_PARAMETER_FOCUS_T focus = {{MMAL_PARAMETER_FOCUS, sizeof(focus)},MMAL_PARAM_FOCUS_FIXED_HYPERFOCAL};
1015 MMAL_STATUS_T result;
1017 result = mmal_port_parameter_set(camera->control, &focus.hdr);
1018 if (result != MMAL_SUCCESS)
1020 LOG_ERROR("Failed to set focus to HYPERFOCAL, result %d", result);
1023 focus.value = focus_setting;
1024 result = mmal_port_parameter_set(camera->control, &focus.hdr);
1025 if (result != MMAL_SUCCESS)
1027 LOG_ERROR("Failed to set focus to %d, result %d", focus_setting, result);
1033 /*****************************************************************************/
1034 static MMAL_BOOL_T mmalcam_next_drc(MMAL_COMPONENT_T *camera)
1036 static const MMAL_PARAMETER_DRC_STRENGTH_T drc_setting[] = {
1037 MMAL_PARAMETER_DRC_STRENGTH_OFF,
1038 MMAL_PARAMETER_DRC_STRENGTH_LOW,
1039 MMAL_PARAMETER_DRC_STRENGTH_MEDIUM,
1040 MMAL_PARAMETER_DRC_STRENGTH_HIGH
1042 static unsigned int index;
1043 MMAL_STATUS_T result;
1044 MMAL_PARAMETER_DRC_T drc = {{MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION,sizeof(drc)},0};
1045 MMAL_PARAMETER_DRC_T drc_check = {{MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION,sizeof(drc_check)},0};
1048 if(index >= countof(drc_setting))
1050 drc.strength = drc_setting[index];
1052 result = mmal_port_parameter_set(camera->control, &drc.hdr);
1053 if (result != MMAL_SUCCESS)
1055 LOG_ERROR("Failed to set drc, %d", result);
1058 result = mmal_port_parameter_get(camera->control, &drc_check.hdr);
1059 if (result != MMAL_SUCCESS)
1061 LOG_ERROR("Failed to retrieve drc, %d", result);
1064 if (memcmp(&drc, &drc_check, sizeof(drc)) != 0)
1066 LOG_ERROR("DRC set (%d) was not retrieved (%d)", drc.strength, drc_check.strength);
1072 /*****************************************************************************/
1073 static MMAL_BOOL_T mmalcam_next_hdr(MMAL_COMPONENT_T *camera)
1075 static const MMAL_BOOL_T hdr_setting[] = {
1079 static unsigned int index;
1080 MMAL_STATUS_T result;
1081 MMAL_PARAMETER_BOOLEAN_T hdr = {{MMAL_PARAMETER_HIGH_DYNAMIC_RANGE,sizeof(hdr)},0};
1082 MMAL_PARAMETER_BOOLEAN_T hdr_check = {{MMAL_PARAMETER_HIGH_DYNAMIC_RANGE,sizeof(hdr_check)},0};
1085 if(index >= countof(hdr_setting))
1087 hdr.enable = hdr_setting[index];
1089 result = mmal_port_parameter_set(camera->control, &hdr.hdr);
1090 if (result != MMAL_SUCCESS)
1092 LOG_ERROR("Failed to set hdr, %d", result);
1095 result = mmal_port_parameter_get(camera->control, &hdr_check.hdr);
1096 if (result != MMAL_SUCCESS)
1098 LOG_ERROR("Failed to retrieve hdr, %d", result);
1101 if (memcmp(&hdr, &hdr_check, sizeof(hdr)) != 0)
1103 LOG_ERROR("HDR set (%d) was not retrieved (%d)", hdr.enable, hdr_check.enable);
1109 /*****************************************************************************/
1110 /* Contrast, brightness, saturation, and sharpness all take the same format,
1111 * but need different parameter IDs, and brightness is 0-100, not -100 to 100.
1113 static MMAL_BOOL_T mmalcam_next_colour_param(MMAL_COMPONENT_T *camera, uint32_t id, int min, int max, const char *param_name)
1115 static MMAL_PARAMETER_RATIONAL_T param = {{MMAL_PARAMETER_GROUP_CAMERA,sizeof(param)},{0,100}};
1116 MMAL_PARAMETER_RATIONAL_T param_check = {{MMAL_PARAMETER_GROUP_CAMERA,sizeof(param_check)},{0,100}};
1117 MMAL_STATUS_T result;
1119 param_check.hdr.id = id;
1121 param.value.num += 20;
1122 if(param.value.num < min || param.value.num > max)
1123 param.value.num = min;
1124 result = mmal_port_parameter_set(camera->control, ¶m.hdr);
1125 if (result != MMAL_SUCCESS)
1127 LOG_ERROR("Failed to set %s, %d", param_name, result);
1130 result = mmal_port_parameter_get(camera->control, ¶m_check.hdr);
1131 if (result != MMAL_SUCCESS)
1133 LOG_ERROR("Failed to retrieve %s, %d", param_name, result);
1136 if (memcmp(¶m, ¶m_check, sizeof(param)) != 0)
1138 LOG_ERROR("%s set (%d/%d) was not retrieved (%d/%d)", param_name,
1139 param.value.num, param.value.den,
1140 param_check.value.num, param_check.value.den);
1147 /*****************************************************************************/
1148 static MMAL_COMPONENT_T *test_video_render_create(MMALCAM_BEHAVIOUR_T *behaviour, MMAL_STATUS_T *status)
1150 MMAL_COMPONENT_T *render = 0;
1151 MMAL_PORT_T *render_port = NULL;
1153 *status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &render);
1154 if(*status != MMAL_SUCCESS)
1156 LOG_ERROR("couldn't create video render");
1159 if(!render->input_num)
1161 LOG_ERROR("video render doesn't have input ports");
1162 *status = MMAL_EINVAL;
1166 render_port = render->input[0];
1168 /* Give higher priority to the overlay layer */
1169 MMAL_DISPLAYREGION_T param;
1170 param.hdr.id = MMAL_PARAMETER_DISPLAYREGION;
1171 param.hdr.size = sizeof(MMAL_DISPLAYREGION_T);
1172 param.set = MMAL_DISPLAY_SET_LAYER;
1173 param.layer = behaviour->layer;
1174 if (behaviour->display_area.width && behaviour->display_area.height)
1176 param.set |= MMAL_DISPLAY_SET_DEST_RECT | MMAL_DISPLAY_SET_FULLSCREEN;
1177 param.fullscreen = 0;
1178 param.dest_rect = behaviour->display_area;
1180 *status = mmal_port_parameter_set( render_port, ¶m.hdr );
1181 if (*status != MMAL_SUCCESS && *status != MMAL_ENOSYS)
1183 LOG_ERROR("could not set video render display properties (%u)", *status);
1187 if (enable_zero_copy())
1189 MMAL_PARAMETER_BOOLEAN_T param_zc =
1190 {{MMAL_PARAMETER_ZERO_COPY, sizeof(MMAL_PARAMETER_BOOLEAN_T)}, 1};
1191 *status = mmal_port_parameter_set(render_port, ¶m_zc.hdr);
1192 if (*status != MMAL_SUCCESS && *status != MMAL_ENOSYS)
1194 LOG_ERROR("failed to set zero copy on render input");
1197 LOG_INFO("enabled zero copy on render");
1200 if (behaviour->opaque)
1202 render_port->format->encoding = MMAL_ENCODING_OPAQUE;
1205 /* Enable component */
1206 *status = mmal_component_enable(render);
1209 LOG_ERROR("video render component couldn't be enabled (%u)", *status);
1216 if(render) mmal_component_destroy(render);
1220 /*****************************************************************************/
1221 static MMAL_COMPONENT_T *test_video_encoder_create(MMALCAM_BEHAVIOUR_T *behaviour, MMAL_STATUS_T *status)
1223 MMAL_COMPONENT_T *encoder = 0;
1224 MMAL_PORT_T *encoder_input = NULL, *encoder_output = NULL;
1225 const char *component_name = MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER;
1228 /* Set the port format */
1229 if (parse_vformat(behaviour->vformat, 0, 0, &encoding))
1231 *status = MMAL_EINVAL;
1235 if (encoding == MMAL_ENCODING_JPEG)
1236 component_name = MMAL_COMPONENT_DEFAULT_IMAGE_ENCODER;
1238 *status = mmal_component_create(component_name, &encoder);
1239 if(*status != MMAL_SUCCESS)
1241 LOG_ERROR("couldn't create video encoder");
1244 if(!encoder->input_num || !encoder->output_num)
1246 LOG_ERROR("video encoder doesn't have input/output ports");
1247 *status = MMAL_EINVAL;
1251 encoder_input = encoder->input[0];
1252 encoder_output = encoder->output[0];
1254 mmal_format_copy(encoder_output->format, encoder_input->format);
1255 encoder_output->format->encoding = encoding;
1256 encoder_output->format->bitrate = behaviour->bit_rate;
1257 *status = mmal_port_format_commit(encoder_output);
1258 if(*status != MMAL_SUCCESS)
1260 LOG_ERROR("format not set on video encoder output port");
1263 encoder_output->buffer_size = encoder_output->buffer_size_recommended;
1264 if (encoder_output->buffer_size < encoder_output->buffer_size_min)
1265 encoder_output->buffer_size = encoder_output->buffer_size_min;
1266 encoder_output->buffer_num = encoder_output->buffer_num_recommended;
1267 if (encoder_output->buffer_num < encoder_output->buffer_num_min)
1268 encoder_output->buffer_num = encoder_output->buffer_num_min;
1270 if (enable_zero_copy())
1272 MMAL_PARAMETER_BOOLEAN_T param_zc =
1273 {{MMAL_PARAMETER_ZERO_COPY, sizeof(MMAL_PARAMETER_BOOLEAN_T)}, 1};
1274 *status = mmal_port_parameter_set(encoder_output, ¶m_zc.hdr);
1275 if (*status != MMAL_SUCCESS && *status != MMAL_ENOSYS)
1277 LOG_ERROR("failed to set zero copy on encoder output");
1280 *status = mmal_port_parameter_set(encoder_input, ¶m_zc.hdr);
1281 if (*status != MMAL_SUCCESS && *status != MMAL_ENOSYS)
1283 LOG_ERROR("failed to set zero copy on encoder input");
1286 LOG_INFO("enabled zero copy on encoder");
1289 if (behaviour->opaque)
1291 encoder_input->format->encoding = MMAL_ENCODING_OPAQUE;
1294 /* Enable component */
1295 *status = mmal_component_enable(encoder);
1298 LOG_ERROR("video encoder component couldn't be enabled");
1305 if(encoder) mmal_component_destroy(encoder);
1310 /*****************************************************************************/
1311 static MMAL_STATUS_T test_container_to_mmal_status(VC_CONTAINER_STATUS_T status)
1315 case VC_CONTAINER_SUCCESS:
1316 case VC_CONTAINER_ERROR_NOT_READY:
1317 return MMAL_SUCCESS;
1318 case VC_CONTAINER_ERROR_LIMIT_REACHED:
1319 case VC_CONTAINER_ERROR_OUT_OF_SPACE:
1321 case VC_CONTAINER_ERROR_URI_NOT_FOUND:
1328 /*****************************************************************************/
1329 static VC_CONTAINER_T *test_container_open(const char *uri, MMAL_ES_FORMAT_T *format, MMAL_STATUS_T *p_status)
1331 VC_CONTAINER_T *container = 0;
1332 VC_CONTAINER_STATUS_T status = VC_CONTAINER_ERROR_FAILED;
1333 VC_CONTAINER_ES_FORMAT_T *container_format = 0;
1335 /* Open container */
1336 container = vc_container_open_writer(uri, &status, 0, 0);
1337 if(status != VC_CONTAINER_SUCCESS)
1339 LOG_ERROR("error opening uri %s (%i)", uri, status);
1343 /* Set format from MMAL port format */
1344 container_format = vc_container_format_create(0);
1345 if (!container_format)
1347 status = VC_CONTAINER_ERROR_OUT_OF_MEMORY;
1348 LOG_ERROR("error (%i)", status);
1352 switch (format->type)
1354 case MMAL_ES_TYPE_VIDEO:
1355 container_format->es_type = VC_CONTAINER_ES_TYPE_VIDEO;
1358 status = VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
1359 LOG_ERROR("unsupported elementary stream format error (%i)", status);
1363 container_format->codec = test_container_encoding_to_codec(format->encoding);
1364 if(format->encoding == MMAL_ENCODING_H264)
1365 container_format->codec_variant = VC_FOURCC('a','v','c','C');
1366 container_format->type->video.width = format->es->video.width;
1367 container_format->type->video.height = format->es->video.height;
1368 container_format->type->video.frame_rate_num = format->es->video.frame_rate.num;
1369 container_format->type->video.frame_rate_den = format->es->video.frame_rate.den;
1370 container_format->type->video.par_num = format->es->video.par.num;
1371 container_format->type->video.par_den = format->es->video.par.den;
1372 container_format->bitrate = format->bitrate;
1373 container_format->flags |= VC_CONTAINER_ES_FORMAT_FLAG_FRAMED;
1375 container_format->extradata_size = 0;
1377 status = vc_container_control(container, VC_CONTAINER_CONTROL_TRACK_ADD, container_format);
1378 if(status != VC_CONTAINER_SUCCESS)
1380 LOG_ERROR("error adding track (%i)", status);
1384 vc_container_control(container, VC_CONTAINER_CONTROL_TRACK_ADD_DONE);
1387 if (container_format)
1388 vc_container_format_delete(container_format);
1389 if (p_status) *p_status = test_container_to_mmal_status(status);
1394 vc_container_close(container);
1400 /*****************************************************************************/
1401 static MMAL_STATUS_T test_container_write(VC_CONTAINER_T *container, MMAL_BUFFER_HEADER_T *buffer)
1403 VC_CONTAINER_PACKET_T packet;
1404 VC_CONTAINER_STATUS_T status;
1405 memset(&packet, 0, sizeof(packet));
1406 static int first_fragment = 1;
1409 if (buffer->flags & MMAL_BUFFER_HEADER_FLAG_CONFIG)
1410 buffer->length = 0; /* Discard codec config data arriving in buffers */
1413 if (buffer->length == 0)
1414 return MMAL_SUCCESS;
1417 packet.pts = buffer->pts == MMAL_TIME_UNKNOWN ? VC_CONTAINER_TIME_UNKNOWN : buffer->pts;
1418 packet.dts = buffer->dts == MMAL_TIME_UNKNOWN ? VC_CONTAINER_TIME_UNKNOWN : buffer->dts;
1419 if(buffer->flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
1420 packet.flags |= VC_CONTAINER_PACKET_FLAG_KEYFRAME;
1421 if(first_fragment || (buffer->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_START))
1423 packet.flags |= VC_CONTAINER_PACKET_FLAG_FRAME_START;
1427 if(buffer->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END)
1429 packet.flags |= VC_CONTAINER_PACKET_FLAG_FRAME_END;
1430 first_fragment = 1; /* Next buffer will be the first fragment */
1433 packet.size = packet.buffer_size = buffer->length;
1434 if ((packet.flags & VC_CONTAINER_PACKET_FLAG_FRAME) == VC_CONTAINER_PACKET_FLAG_FRAME)
1435 packet.frame_size = packet.size;
1437 vcos_assert(buffer->offset == 0);
1439 packet.data = buffer->data;
1441 LOG_DEBUG("writing packet: track %i, size %i/%i, pts %"PRId64", flags %x%s",
1442 packet.track, packet.size, packet.frame_size, packet.pts,
1443 packet.flags, (packet.flags & VC_CONTAINER_PACKET_FLAG_KEYFRAME) ? " (keyframe)" : "");
1445 status = vc_container_write(container, &packet);
1447 return test_container_to_mmal_status(status);
1450 /*****************************************************************************/
1452 VC_CONTAINER_FOURCC_T codec;
1454 } codec_to_encoding_table[] =
1456 {VC_CONTAINER_CODEC_H263, MMAL_ENCODING_H263},
1457 {VC_CONTAINER_CODEC_H264, MMAL_ENCODING_H264},
1458 {VC_CONTAINER_CODEC_MP4V, MMAL_ENCODING_MP4V},
1459 {VC_CONTAINER_CODEC_MP2V, MMAL_ENCODING_MP2V},
1460 {VC_CONTAINER_CODEC_MP1V, MMAL_ENCODING_MP1V},
1461 {VC_CONTAINER_CODEC_WMV3, MMAL_ENCODING_WMV3},
1462 {VC_CONTAINER_CODEC_WMV2, MMAL_ENCODING_WMV2},
1463 {VC_CONTAINER_CODEC_WMV1, MMAL_ENCODING_WMV1},
1464 {VC_CONTAINER_CODEC_WVC1, MMAL_ENCODING_WVC1},
1465 {VC_CONTAINER_CODEC_VP6, MMAL_ENCODING_VP6},
1466 {VC_CONTAINER_CODEC_VP7, MMAL_ENCODING_VP7},
1467 {VC_CONTAINER_CODEC_VP8, MMAL_ENCODING_VP8},
1468 {VC_CONTAINER_CODEC_THEORA, MMAL_ENCODING_THEORA},
1469 {VC_CONTAINER_CODEC_UNKNOWN, MMAL_ENCODING_UNKNOWN}
1472 static VC_CONTAINER_FOURCC_T test_container_encoding_to_codec(uint32_t encoding)
1475 for(i = 0; codec_to_encoding_table[i].codec != VC_CONTAINER_CODEC_UNKNOWN; i++)
1476 if(codec_to_encoding_table[i].encoding == encoding) break;
1477 return codec_to_encoding_table[i].codec;