Beispiel #1
0
/** Create an instance of a component  */
static MMAL_STATUS_T mmal_component_create_splitter(const char *name, MMAL_COMPONENT_T *component)
{
   MMAL_COMPONENT_MODULE_T *module;
   MMAL_STATUS_T status = MMAL_ENOMEM;
   unsigned int i;
   MMAL_PARAM_UNUSED(name);

   /* Allocate the context for our module */
   component->priv->module = module = vcos_malloc(sizeof(*module), "mmal module");
   if (!module)
      return MMAL_ENOMEM;
   memset(module, 0, sizeof(*module));

   component->priv->pf_destroy = splitter_component_destroy;

   /* Allocate and initialise all the ports for this component */
   component->input = mmal_ports_alloc(component, 1, MMAL_PORT_TYPE_INPUT, sizeof(MMAL_PORT_MODULE_T));
   if(!component->input)
      goto error;
   component->input_num = 1;
   component->input[0]->priv->pf_enable = splitter_port_enable;
   component->input[0]->priv->pf_disable = splitter_port_disable;
   component->input[0]->priv->pf_flush = splitter_port_flush;
   component->input[0]->priv->pf_send = splitter_port_send;
   component->input[0]->priv->pf_set_format = splitter_port_format_commit;
   component->input[0]->priv->pf_parameter_set = splitter_port_parameter_set;
   component->input[0]->buffer_num_min = 1;
   component->input[0]->buffer_num_recommended = 0;
   component->input[0]->priv->module->queue = mmal_queue_create();
   if(!component->input[0]->priv->module->queue)
      goto error;

   component->output = mmal_ports_alloc(component, SPLITTER_OUTPUT_PORTS_NUM,
                                        MMAL_PORT_TYPE_OUTPUT, sizeof(MMAL_PORT_MODULE_T));
   if(!component->output)
      goto error;
   component->output_num = SPLITTER_OUTPUT_PORTS_NUM;
   for(i = 0; i < component->output_num; i++)
   {
      component->output[i]->priv->pf_enable = splitter_port_enable;
      component->output[i]->priv->pf_disable = splitter_port_disable;
      component->output[i]->priv->pf_flush = splitter_port_flush;
      component->output[i]->priv->pf_send = splitter_port_send;
      component->output[i]->priv->pf_set_format = splitter_port_format_commit;
      component->output[i]->priv->pf_parameter_set = splitter_port_parameter_set;
      component->output[i]->buffer_num_min = 1;
      component->output[i]->buffer_num_recommended = 0;
      component->output[i]->capabilities = MMAL_PORT_CAPABILITY_PASSTHROUGH;
      component->output[i]->priv->module->queue = mmal_queue_create();
      if(!component->output[i]->priv->module->queue)
         goto error;
   }

   return MMAL_SUCCESS;

 error:
   splitter_component_destroy(component);
   return status;
}
Beispiel #2
0
CMMALRenderer::CMMALRenderer()
: CThread("CMMALRenderer")
{
  CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__);
  m_vout = NULL;
  m_vout_input = NULL;
  m_vout_input_pool = NULL;
  memset(m_buffers, 0, sizeof m_buffers);
  m_release_queue = mmal_queue_create();
  Create();
}
/** Create an instance of a component  */
static MMAL_STATUS_T mmal_component_create_sdl(const char *name, MMAL_COMPONENT_T *component)
{
   MMAL_COMPONENT_MODULE_T *module;
   MMAL_STATUS_T status = MMAL_ENOMEM;

   /* Check we're the requested component */
   if(strcmp(name, "sdl." MMAL_VIDEO_RENDER))
      return MMAL_ENOENT;

   if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_EVENTTHREAD|SDL_INIT_NOPARACHUTE) < 0)
      return MMAL_ENXIO;

   /* Allocate our module context */
   component->priv->module = module = vcos_calloc(1, sizeof(*module), "mmal module");
   if(!module) return MMAL_ENOMEM;

   module->queue = mmal_queue_create();
   if(!module->queue) goto error;

   /* Allocate the ports for this component */
   component->input = mmal_ports_alloc(component, 1, MMAL_PORT_TYPE_INPUT, 0);
   if(!component->input) goto error;
   component->input_num = 1;
   module->display_region.width = SDL_WIDTH;
   module->display_region.height = SDL_HEIGHT;

   /************/

   component->input[0]->priv->pf_set_format = sdl_port_set_format;
   component->input[0]->priv->pf_enable = sdl_port_enable;
   component->input[0]->priv->pf_disable = sdl_port_disable;
   component->input[0]->priv->pf_flush = sdl_port_flush;
   component->input[0]->priv->pf_send = sdl_port_send;
   component->input[0]->priv->pf_parameter_set = sdl_port_parameter_set;
   component->input[0]->buffer_num_min = INPUT_MIN_BUFFER_NUM;
   component->input[0]->buffer_num_recommended = INPUT_RECOMMENDED_BUFFER_NUM;

   component->priv->pf_destroy = sdl_component_destroy;

   /* Create a thread to monitor SDL events */
   module->thread = SDL_CreateThread(sdl_event_thread, component);

   status = mmal_component_action_register(component, sdl_do_processing_loop);
   if (status != MMAL_SUCCESS)
      goto error;

   return MMAL_SUCCESS;

 error:
   sdl_component_destroy(component);
   return status;
}
Beispiel #4
0
/* Initialise all callbacks and setup internal resources */
static MMAL_STATUS_T mmal_port_clock_setup(MMAL_PORT_T *port, MMAL_PORT_CLOCK_EVENT_CB event_cb)
{
   MMAL_STATUS_T status;

   status = mmal_clock_create(&port->priv->module->clock);
   if (status != MMAL_SUCCESS)
   {
      LOG_ERROR("failed to create clock module on port %s (%s)", port->name, mmal_status_to_string(status));
      return status;
   }
   port->priv->module->clock->user_data = port;

   port->buffer_size = sizeof(MMAL_CLOCK_PAYLOAD_T);
   port->buffer_size_min = sizeof(MMAL_CLOCK_PAYLOAD_T);
   port->buffer_num_min = MMAL_PORT_CLOCK_BUFFERS_MIN;
   port->buffer_num_recommended = MMAL_PORT_CLOCK_BUFFERS_MIN;

   port->priv->module->event_cb = event_cb;
   port->priv->module->queue = mmal_queue_create();
   if (!port->priv->module->queue)
   {
      mmal_clock_destroy(port->priv->module->clock);
      return MMAL_ENOMEM;
   }

   port->priv->pf_set_format = mmal_port_clock_set_format;
   port->priv->pf_enable = mmal_port_clock_enable;
   port->priv->pf_disable = mmal_port_clock_disable;
   port->priv->pf_send = mmal_port_clock_send;
   port->priv->pf_flush = mmal_port_clock_flush;
   port->priv->pf_parameter_set = mmal_port_clock_parameter_set;
   port->priv->pf_parameter_get = mmal_port_clock_parameter_get;
   port->priv->pf_connect = mmal_port_clock_connect;
#ifdef __VIDEOCORE__
   port->priv->pf_payload_alloc = mmal_port_clock_payload_alloc;
   port->priv->pf_payload_free = mmal_port_clock_payload_free;
   port->capabilities = MMAL_PORT_CAPABILITY_ALLOCATION;
#endif

   return status;
}
Beispiel #5
0
static av_cold int ffmmal_init_decoder(AVCodecContext *avctx)
{
    MMALDecodeContext *ctx = avctx->priv_data;
    MMAL_STATUS_T status;
    MMAL_ES_FORMAT_T *format_in;
    MMAL_COMPONENT_T *decoder;
    char tmp[32];
    int ret = 0;

    bcm_host_init();

    if (mmal_vc_init()) {
        av_log(avctx, AV_LOG_ERROR, "Cannot initialize MMAL VC driver!\n");
        return AVERROR(ENOSYS);
    }

    if ((ret = ff_get_format(avctx, avctx->codec->pix_fmts)) < 0)
        return ret;

    avctx->pix_fmt = ret;

    if ((status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &ctx->decoder)))
        goto fail;

    decoder = ctx->decoder;

    format_in = decoder->input[0]->format;
    format_in->type = MMAL_ES_TYPE_VIDEO;
    switch (avctx->codec_id) {
    case AV_CODEC_ID_MPEG2VIDEO:
        format_in->encoding = MMAL_ENCODING_MP2V;
        break;
    case AV_CODEC_ID_MPEG4:
        format_in->encoding = MMAL_ENCODING_MP4V;
        break;
    case AV_CODEC_ID_VC1:
        format_in->encoding = MMAL_ENCODING_WVC1;
        break;
    case AV_CODEC_ID_H264:
    default:
        format_in->encoding = MMAL_ENCODING_H264;
        break;
    }
    format_in->es->video.width = FFALIGN(avctx->width, 32);
    format_in->es->video.height = FFALIGN(avctx->height, 16);
    format_in->es->video.crop.width = avctx->width;
    format_in->es->video.crop.height = avctx->height;
    format_in->es->video.frame_rate.num = 24000;
    format_in->es->video.frame_rate.den = 1001;
    format_in->es->video.par.num = avctx->sample_aspect_ratio.num;
    format_in->es->video.par.den = avctx->sample_aspect_ratio.den;
    format_in->flags = MMAL_ES_FORMAT_FLAG_FRAMED;

    av_get_codec_tag_string(tmp, sizeof(tmp), format_in->encoding);
    av_log(avctx, AV_LOG_DEBUG, "Using MMAL %s encoding.\n", tmp);

#if HAVE_MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS
    if (mmal_port_parameter_set_uint32(decoder->input[0], MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS,
                                       -1 - ctx->extra_decoder_buffers)) {
        av_log(avctx, AV_LOG_WARNING, "Could not set input buffering limit.\n");
    }
#endif

    if ((status = mmal_port_format_commit(decoder->input[0])))
        goto fail;

    decoder->input[0]->buffer_num =
        FFMAX(decoder->input[0]->buffer_num_min, 20);
    decoder->input[0]->buffer_size =
        FFMAX(decoder->input[0]->buffer_size_min, 512 * 1024);
    ctx->pool_in = mmal_pool_create(decoder->input[0]->buffer_num, 0);
    if (!ctx->pool_in) {
        ret = AVERROR(ENOMEM);
        goto fail;
    }

    if ((ret = ffmal_update_format(avctx)) < 0)
        goto fail;

    ctx->queue_decoded_frames = mmal_queue_create();
    if (!ctx->queue_decoded_frames)
        goto fail;

    decoder->input[0]->userdata = (void*)avctx;
    decoder->output[0]->userdata = (void*)avctx;
    decoder->control->userdata = (void*)avctx;

    if ((status = mmal_port_enable(decoder->control, control_port_cb)))
        goto fail;
    if ((status = mmal_port_enable(decoder->input[0], input_callback)))
        goto fail;
    if ((status = mmal_port_enable(decoder->output[0], output_callback)))
        goto fail;

    if ((status = mmal_component_enable(decoder)))
        goto fail;

    return 0;

fail:
    ffmmal_close_decoder(avctx);
    return ret < 0 ? ret : AVERROR_UNKNOWN;
}
Beispiel #6
0
static int Open(filter_t *filter)
{
    int32_t frame_duration = filter->fmt_in.video.i_frame_rate != 0 ?
            (int64_t)1000000 * filter->fmt_in.video.i_frame_rate_base /
            filter->fmt_in.video.i_frame_rate : 0;

    MMAL_PARAMETER_IMAGEFX_PARAMETERS_T imfx_param = {
            { MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, sizeof(imfx_param) },
            MMAL_PARAM_IMAGEFX_DEINTERLACE_ADV,
            2,
            { 3, frame_duration }
    };

    int ret = VLC_SUCCESS;
    MMAL_STATUS_T status;
    filter_sys_t *sys;

    msg_Dbg(filter, "Try to open mmal_deinterlace filter. frame_duration: %d!", frame_duration);

    if (filter->fmt_in.video.i_chroma != VLC_CODEC_MMAL_OPAQUE)
        return VLC_EGENERIC;

    if (filter->fmt_out.video.i_chroma != VLC_CODEC_MMAL_OPAQUE)
        return VLC_EGENERIC;

    sys = calloc(1, sizeof(filter_sys_t));
    if (!sys)
        return VLC_ENOMEM;
    filter->p_sys = sys;

    bcm_host_init();

    status = mmal_component_create(MMAL_COMPONENT_DEFAULT_DEINTERLACE, &sys->component);
    if (status != MMAL_SUCCESS) {
        msg_Err(filter, "Failed to create MMAL component %s (status=%"PRIx32" %s)",
                MMAL_COMPONENT_DEFAULT_DEINTERLACE, status, mmal_status_to_string(status));
        ret = VLC_EGENERIC;
        goto out;
    }

    status = mmal_port_parameter_set(sys->component->output[0], &imfx_param.hdr);
    if (status != MMAL_SUCCESS) {
        msg_Err(filter, "Failed to configure MMAL component %s (status=%"PRIx32" %s)",
                MMAL_COMPONENT_DEFAULT_DEINTERLACE, status, mmal_status_to_string(status));
        ret = VLC_EGENERIC;
        goto out;
    }

    sys->component->control->userdata = (struct MMAL_PORT_USERDATA_T *)filter;
    status = mmal_port_enable(sys->component->control, control_port_cb);
    if (status != MMAL_SUCCESS) {
        msg_Err(filter, "Failed to enable control port %s (status=%"PRIx32" %s)",
                sys->component->control->name, status, mmal_status_to_string(status));
        ret = VLC_EGENERIC;
        goto out;
    }

    sys->input = sys->component->input[0];
    sys->input->userdata = (struct MMAL_PORT_USERDATA_T *)filter;
    if (filter->fmt_in.i_codec == VLC_CODEC_MMAL_OPAQUE)
        sys->input->format->encoding = MMAL_ENCODING_OPAQUE;
    sys->input->format->es->video.width = filter->fmt_in.video.i_width;
    sys->input->format->es->video.height = filter->fmt_in.video.i_height;
    sys->input->format->es->video.crop.x = 0;
    sys->input->format->es->video.crop.y = 0;
    sys->input->format->es->video.crop.width = filter->fmt_in.video.i_width;
    sys->input->format->es->video.crop.height = filter->fmt_in.video.i_height;
    sys->input->format->es->video.par.num = filter->fmt_in.video.i_sar_num;
    sys->input->format->es->video.par.den = filter->fmt_in.video.i_sar_den;

    es_format_Copy(&filter->fmt_out, &filter->fmt_in);
    filter->fmt_out.video.i_frame_rate *= 2;

    status = mmal_port_format_commit(sys->input);
    if (status != MMAL_SUCCESS) {
        msg_Err(filter, "Failed to commit format for input port %s (status=%"PRIx32" %s)",
                        sys->input->name, status, mmal_status_to_string(status));
        ret = VLC_EGENERIC;
        goto out;
    }
    sys->input->buffer_size = sys->input->buffer_size_recommended;
    sys->input->buffer_num = sys->input->buffer_num_recommended;

    if (filter->fmt_in.i_codec == VLC_CODEC_MMAL_OPAQUE) {
        MMAL_PARAMETER_BOOLEAN_T zero_copy = {
            { MMAL_PARAMETER_ZERO_COPY, sizeof(MMAL_PARAMETER_BOOLEAN_T) },
            1
        };

        status = mmal_port_parameter_set(sys->input, &zero_copy.hdr);
        if (status != MMAL_SUCCESS) {
           msg_Err(filter, "Failed to set zero copy on port %s (status=%"PRIx32" %s)",
                    sys->input->name, status, mmal_status_to_string(status));
           goto out;
        }
    }

    status = mmal_port_enable(sys->input, input_port_cb);
    if (status != MMAL_SUCCESS) {
        msg_Err(filter, "Failed to enable input port %s (status=%"PRIx32" %s)",
                sys->input->name, status, mmal_status_to_string(status));
        ret = VLC_EGENERIC;
        goto out;
    }

    sys->output = sys->component->output[0];
    sys->output->userdata = (struct MMAL_PORT_USERDATA_T *)filter;
    mmal_format_full_copy(sys->output->format, sys->input->format);

    status = mmal_port_format_commit(sys->output);
    if (status != MMAL_SUCCESS) {
        msg_Err(filter, "Failed to commit format for output port %s (status=%"PRIx32" %s)",
                        sys->input->name, status, mmal_status_to_string(status));
        ret = VLC_EGENERIC;
        goto out;
    }

    sys->output->buffer_num = 3;

    if (filter->fmt_in.i_codec == VLC_CODEC_MMAL_OPAQUE) {
        MMAL_PARAMETER_BOOLEAN_T zero_copy = {
            { MMAL_PARAMETER_ZERO_COPY, sizeof(MMAL_PARAMETER_BOOLEAN_T) },
            1
        };

        status = mmal_port_parameter_set(sys->output, &zero_copy.hdr);
        if (status != MMAL_SUCCESS) {
           msg_Err(filter, "Failed to set zero copy on port %s (status=%"PRIx32" %s)",
                    sys->output->name, status, mmal_status_to_string(status));
           goto out;
        }
    }

    status = mmal_port_enable(sys->output, output_port_cb);
    if (status != MMAL_SUCCESS) {
        msg_Err(filter, "Failed to enable output port %s (status=%"PRIx32" %s)",
                sys->output->name, status, mmal_status_to_string(status));
        ret = VLC_EGENERIC;
        goto out;
    }

    status = mmal_component_enable(sys->component);
    if (status != MMAL_SUCCESS) {
        msg_Err(filter, "Failed to enable component %s (status=%"PRIx32" %s)",
                sys->component->name, status, mmal_status_to_string(status));
        ret = VLC_EGENERIC;
        goto out;
    }

    sys->filtered_pictures = mmal_queue_create();

    filter->pf_video_filter = deinterlace;
    filter->pf_video_flush = flush;
    vlc_mutex_init_recursive(&sys->mutex);
    vlc_mutex_init(&sys->buffer_cond_mutex);
    vlc_cond_init(&sys->buffer_cond);

out:
    if (ret != VLC_SUCCESS)
        Close(filter);

    return ret;
}
bool CCameraOutput::Init(int width, int height, MMAL_COMPONENT_T* input_component, int input_port_idx, bool do_argb_conversion)
{
	printf("Init camera output with %d/%d\n",width,height);
	Width = width;
	Height = height;

	MMAL_COMPONENT_T *resizer = 0;
	MMAL_CONNECTION_T* connection = 0;
	MMAL_STATUS_T status;
	MMAL_POOL_T* video_buffer_pool = 0;
	MMAL_QUEUE_T* output_queue = 0;

	//got the port we're receiving from
	MMAL_PORT_T* input_port = input_component->output[input_port_idx];

	//check if user wants conversion to argb or the width or height is different to the input
	if(do_argb_conversion || width != input_port->format->es->video.width || height != input_port->format->es->video.height)
	{
		//create the resizing component, reading from the splitter output
		resizer = CreateResizeComponentAndSetupPorts(input_port,do_argb_conversion);
		if(!resizer)
			goto error;

		//create and enable a connection between the video output and the resizer input
		status = mmal_connection_create(&connection, input_port, resizer->input[0], MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT);
		if (status != MMAL_SUCCESS)
		{
			printf("Failed to create connection\n");
			goto error;
		}
		status = mmal_connection_enable(connection);
		if (status != MMAL_SUCCESS)
		{
			printf("Failed to enable connection\n");
			goto error;
		}

		//set the buffer pool port to be the resizer output
		BufferPort = resizer->output[0];
	}
	else
	{
		//no convert/resize needed so just set the buffer pool port to be the input port
		BufferPort = input_port;
	}

	//setup the video buffer callback
	video_buffer_pool = EnablePortCallbackAndCreateBufferPool(BufferPort,VideoBufferCallback,3);
	if(!video_buffer_pool)
		goto error;

	//create the output queue
	output_queue = mmal_queue_create();
	if(!output_queue)
	{
		printf("Failed to create output queue\n");
		goto error;
	}

	ResizerComponent = resizer;
	BufferPool = video_buffer_pool;
	OutputQueue = output_queue;
	Connection = connection;

	return true;

error:

	if(output_queue)
		mmal_queue_destroy(output_queue);
	if(video_buffer_pool)
		mmal_port_pool_destroy(resizer->output[0],video_buffer_pool);
	if(connection)
		mmal_connection_destroy(connection);
	if(resizer)
		mmal_component_destroy(resizer);

	return false;
}
Beispiel #8
0
int main(int argc, char **argv)
{
   MMAL_STATUS_T status = MMAL_EINVAL;
   MMAL_COMPONENT_T *decoder = 0;
   MMAL_POOL_T *pool_in = 0, *pool_out = 0;
   unsigned int count;

   if (argc < 2)
   {
      fprintf(stderr, "invalid arguments\n");
      return -1;
   }

#ifndef WIN32
   // TODO verify that we dont really need to call bcm_host_init
   bcm_host_init();
#endif

   vcos_semaphore_create(&context.semaphore, "example", 1);

   SOURCE_OPEN(argv[1]);

   /* Create the decoder component.
    * This specific component exposes 2 ports (1 input and 1 output). Like most components
    * its expects the format of its input port to be set by the client in order for it to
    * know what kind of data it will be fed. */
   status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &decoder);
   CHECK_STATUS(status, "failed to create decoder");

   /* Set format of video decoder input port */
   MMAL_ES_FORMAT_T *format_in = decoder->input[0]->format;
   format_in->type = MMAL_ES_TYPE_VIDEO;
   format_in->encoding = MMAL_ENCODING_H264;
   format_in->es->video.width = 1280;
   format_in->es->video.height = 720;
   format_in->es->video.frame_rate.num = 30;
   format_in->es->video.frame_rate.den = 1;
   format_in->es->video.par.num = 1;
   format_in->es->video.par.den = 1;
   /* If the data is known to be framed then the following flag should be set:
    * format_in->flags |= MMAL_ES_FORMAT_FLAG_FRAMED; */

   SOURCE_READ_CODEC_CONFIG_DATA(codec_header_bytes, codec_header_bytes_size);
   status = mmal_format_extradata_alloc(format_in, codec_header_bytes_size);
   CHECK_STATUS(status, "failed to allocate extradata");
   format_in->extradata_size = codec_header_bytes_size;
   if (format_in->extradata_size)
      memcpy(format_in->extradata, codec_header_bytes, format_in->extradata_size);

   status = mmal_port_format_commit(decoder->input[0]);
   CHECK_STATUS(status, "failed to commit format");

   /* Display the output port format */
   MMAL_ES_FORMAT_T *format_out = decoder->output[0]->format;
   fprintf(stderr, "%s\n", decoder->output[0]->name);
   fprintf(stderr, " type: %i, fourcc: %4.4s\n", format_out->type, (char *)&format_out->encoding);
   fprintf(stderr, " bitrate: %i, framed: %i\n", format_out->bitrate,
           !!(format_out->flags & MMAL_ES_FORMAT_FLAG_FRAMED));
   fprintf(stderr, " extra data: %i, %p\n", format_out->extradata_size, format_out->extradata);
   fprintf(stderr, " width: %i, height: %i, (%i,%i,%i,%i)\n",
           format_out->es->video.width, format_out->es->video.height,
           format_out->es->video.crop.x, format_out->es->video.crop.y,
           format_out->es->video.crop.width, format_out->es->video.crop.height);

   /* The format of both ports is now set so we can get their buffer requirements and create
    * our buffer headers. We use the buffer pool API to create these. */
   decoder->input[0]->buffer_num = decoder->input[0]->buffer_num_min;
   decoder->input[0]->buffer_size = decoder->input[0]->buffer_size_min;
   decoder->output[0]->buffer_num = decoder->output[0]->buffer_num_min;
   decoder->output[0]->buffer_size = decoder->output[0]->buffer_size_min;
   pool_in = mmal_pool_create(decoder->input[0]->buffer_num,
                              decoder->input[0]->buffer_size);
   pool_out = mmal_pool_create(decoder->output[0]->buffer_num,
                               decoder->output[0]->buffer_size);

   /* Create a queue to store our decoded video frames. The callback we will get when
    * a frame has been decoded will put the frame into this queue. */
   context.queue = mmal_queue_create();

   /* Store a reference to our context in each port (will be used during callbacks) */
   decoder->input[0]->userdata = (void *)&context;
   decoder->output[0]->userdata = (void *)&context;

   /* Enable all the input port and the output port.
    * The callback specified here is the function which will be called when the buffer header
    * we sent to the component has been processed. */
   status = mmal_port_enable(decoder->input[0], input_callback);
   CHECK_STATUS(status, "failed to enable input port");
   status = mmal_port_enable(decoder->output[0], output_callback);
   CHECK_STATUS(status, "failed to enable output port");

   /* Component won't start processing data until it is enabled. */
   status = mmal_component_enable(decoder);
   CHECK_STATUS(status, "failed to enable component");

   /* Start decoding */
   fprintf(stderr, "start decoding\n");

   /* This is the main processing loop */
   for (count = 0; count < 500; count++)
   {
      MMAL_BUFFER_HEADER_T *buffer;

      /* Wait for buffer headers to be available on either of the decoder ports */
      vcos_semaphore_wait(&context.semaphore);

      /* Send data to decode to the input port of the video decoder */
      if ((buffer = mmal_queue_get(pool_in->queue)) != NULL)
      {
         SOURCE_READ_DATA_INTO_BUFFER(buffer);
         if (!buffer->length)
            break;

         fprintf(stderr, "sending %i bytes\n", (int)buffer->length);
         status = mmal_port_send_buffer(decoder->input[0], buffer);
         CHECK_STATUS(status, "failed to send buffer");
      }

      /* Get our decoded frames */
      while ((buffer = mmal_queue_get(context.queue)) != NULL)
      {
         /* We have a frame, do something with it (why not display it for instance?).
          * Once we're done with it, we release it. It will automatically go back
          * to its original pool so it can be reused for a new video frame.
          */
         fprintf(stderr, "decoded frame\n");
         mmal_buffer_header_release(buffer);
      }

      /* Send empty buffers to the output port of the decoder */
      while ((buffer = mmal_queue_get(pool_out->queue)) != NULL)
      {
         status = mmal_port_send_buffer(decoder->output[0], buffer);
         CHECK_STATUS(status, "failed to send buffer");
      }
   }

   /* Stop decoding */
   fprintf(stderr, "stop decoding\n");

   /* Stop everything. Not strictly necessary since mmal_component_destroy()
    * will do that anyway */
   mmal_port_disable(decoder->input[0]);
   mmal_port_disable(decoder->output[0]);
   mmal_component_disable(decoder);

 error:
   /* Cleanup everything */
   if (decoder)
      mmal_component_destroy(decoder);
   if (pool_in)
      mmal_pool_destroy(pool_in);
   if (pool_out)
      mmal_pool_destroy(pool_out);
   if (context.queue)
      mmal_queue_destroy(context.queue);

   SOURCE_CLOSE();
   vcos_semaphore_delete(&context.semaphore);
   return status == MMAL_SUCCESS ? 0 : -1;
}
Beispiel #9
0
static int OpenDecoder(decoder_t *dec)
{
    int ret = VLC_SUCCESS;
    decoder_sys_t *sys;
    MMAL_PARAMETER_UINT32_T extra_buffers;
    MMAL_STATUS_T status;

    if (dec->fmt_in.i_cat != VIDEO_ES)
        return VLC_EGENERIC;

    if (dec->fmt_in.i_codec != VLC_CODEC_MPGV &&
            dec->fmt_in.i_codec != VLC_CODEC_H264)
        return VLC_EGENERIC;

    sys = calloc(1, sizeof(decoder_sys_t));
    if (!sys) {
        ret = VLC_ENOMEM;
        goto out;
    }
    dec->p_sys = sys;
    dec->b_need_packetized = true;

    sys->opaque = var_InheritBool(dec, MMAL_OPAQUE_NAME);
    bcm_host_init();

    status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &sys->component);
    if (status != MMAL_SUCCESS) {
        msg_Err(dec, "Failed to create MMAL component %s (status=%"PRIx32" %s)",
                MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, status, mmal_status_to_string(status));
        ret = VLC_EGENERIC;
        goto out;
    }

    sys->component->control->userdata = (struct MMAL_PORT_USERDATA_T *)dec;
    status = mmal_port_enable(sys->component->control, control_port_cb);
    if (status != MMAL_SUCCESS) {
        msg_Err(dec, "Failed to enable control port %s (status=%"PRIx32" %s)",
                sys->component->control->name, status, mmal_status_to_string(status));
        ret = VLC_EGENERIC;
        goto out;
    }

    sys->input = sys->component->input[0];
    sys->input->userdata = (struct MMAL_PORT_USERDATA_T *)dec;
    if (dec->fmt_in.i_codec == VLC_CODEC_MPGV)
        sys->input->format->encoding = MMAL_ENCODING_MP2V;
    else
        sys->input->format->encoding = MMAL_ENCODING_H264;

    if (dec->fmt_in.i_codec == VLC_CODEC_H264) {
        if (dec->fmt_in.i_extra > 0) {
            status = mmal_format_extradata_alloc(sys->input->format,
                    dec->fmt_in.i_extra);
            if (status == MMAL_SUCCESS) {
                memcpy(sys->input->format->extradata, dec->fmt_in.p_extra,
                        dec->fmt_in.i_extra);
                sys->input->format->extradata_size = dec->fmt_in.i_extra;
            } else {
                msg_Err(dec, "Failed to allocate extra format data on input port %s (status=%"PRIx32" %s)",
                        sys->input->name, status, mmal_status_to_string(status));
            }
        }
    }

    status = mmal_port_format_commit(sys->input);
    if (status != MMAL_SUCCESS) {
        msg_Err(dec, "Failed to commit format for input port %s (status=%"PRIx32" %s)",
                sys->input->name, status, mmal_status_to_string(status));
        ret = VLC_EGENERIC;
        goto out;
    }
    sys->input->buffer_size = sys->input->buffer_size_recommended;
    sys->input->buffer_num = sys->input->buffer_num_recommended;

    status = mmal_port_enable(sys->input, input_port_cb);
    if (status != MMAL_SUCCESS) {
        msg_Err(dec, "Failed to enable input port %s (status=%"PRIx32" %s)",
                sys->input->name, status, mmal_status_to_string(status));
        ret = VLC_EGENERIC;
        goto out;
    }

    sys->output = sys->component->output[0];
    sys->output->userdata = (struct MMAL_PORT_USERDATA_T *)dec;

    if (sys->opaque) {
        extra_buffers.hdr.id = MMAL_PARAMETER_EXTRA_BUFFERS;
        extra_buffers.hdr.size = sizeof(MMAL_PARAMETER_UINT32_T);
        extra_buffers.value = NUM_EXTRA_BUFFERS;
        status = mmal_port_parameter_set(sys->output, &extra_buffers.hdr);
        if (status != MMAL_SUCCESS) {
            msg_Err(dec, "Failed to set MMAL_PARAMETER_EXTRA_BUFFERS on output port (status=%"PRIx32" %s)",
                    status, mmal_status_to_string(status));
            ret = VLC_EGENERIC;
            goto out;
        }

        msg_Dbg(dec, "Activate zero-copy for output port");
        MMAL_PARAMETER_BOOLEAN_T zero_copy = {
            { MMAL_PARAMETER_ZERO_COPY, sizeof(MMAL_PARAMETER_BOOLEAN_T) },
            1
        };

        status = mmal_port_parameter_set(sys->output, &zero_copy.hdr);
        if (status != MMAL_SUCCESS) {
           msg_Err(dec, "Failed to set zero copy on port %s (status=%"PRIx32" %s)",
                    sys->output->name, status, mmal_status_to_string(status));
           goto out;
        }
    }

    status = mmal_port_enable(sys->output, output_port_cb);
    if (status != MMAL_SUCCESS) {
        msg_Err(dec, "Failed to enable output port %s (status=%"PRIx32" %s)",
                sys->output->name, status, mmal_status_to_string(status));
        ret = VLC_EGENERIC;
        goto out;
    }

    status = mmal_component_enable(sys->component);
    if (status != MMAL_SUCCESS) {
        msg_Err(dec, "Failed to enable component %s (status=%"PRIx32" %s)",
                sys->component->name, status, mmal_status_to_string(status));
        ret = VLC_EGENERIC;
        goto out;
    }

    sys->input_pool = mmal_pool_create(sys->input->buffer_num, 0);
    sys->decoded_pictures = mmal_queue_create();

    if (sys->opaque) {
        dec->fmt_out.i_codec = VLC_CODEC_MMAL_OPAQUE;
        dec->fmt_out.video.i_chroma = VLC_CODEC_MMAL_OPAQUE;
    } else {
        dec->fmt_out.i_codec = VLC_CODEC_I420;
        dec->fmt_out.video.i_chroma = VLC_CODEC_I420;
    }

    dec->fmt_out.i_cat = VIDEO_ES;
    dec->pf_decode_video = decode;

    vlc_mutex_init_recursive(&sys->mutex);
    vlc_sem_init(&sys->sem, 0);

out:
    if (ret != VLC_SUCCESS)
        CloseDecoder(dec);

    return ret;
}
Beispiel #10
0
static av_cold int ffmmal_init_decoder(AVCodecContext *avctx)
{
    MMALDecodeContext *ctx = avctx->priv_data;
    MMAL_STATUS_T status;
    MMAL_ES_FORMAT_T *format_in;
    MMAL_COMPONENT_T *decoder;
    int ret = 0;

    bcm_host_init();

    if (mmal_vc_init()) {
        av_log(avctx, AV_LOG_ERROR, "Cannot initialize MMAL VC driver!\n");
        return AVERROR(ENOSYS);
    }

    if ((ret = ff_get_format(avctx, avctx->codec->pix_fmts)) < 0)
        return ret;

    avctx->pix_fmt = ret;

    if ((status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &ctx->decoder)))
        goto fail;

    decoder = ctx->decoder;

    format_in = decoder->input[0]->format;
    format_in->type = MMAL_ES_TYPE_VIDEO;
    format_in->encoding = MMAL_ENCODING_H264;
    format_in->es->video.width = FFALIGN(avctx->width, 32);
    format_in->es->video.height = FFALIGN(avctx->height, 16);
    format_in->es->video.crop.width = avctx->width;
    format_in->es->video.crop.height = avctx->height;
    format_in->es->video.frame_rate.num = 24000;
    format_in->es->video.frame_rate.den = 1001;
    format_in->es->video.par.num = avctx->sample_aspect_ratio.num;
    format_in->es->video.par.den = avctx->sample_aspect_ratio.den;
    format_in->flags = MMAL_ES_FORMAT_FLAG_FRAMED;

    if (avctx->codec->id == AV_CODEC_ID_H264 && avctx->extradata && avctx->extradata[0] == 1) {
        uint8_t *dummy_p;
        int dummy_int;
        ctx->bsfc = av_bitstream_filter_init("h264_mp4toannexb");
        if (!ctx->bsfc) {
            av_log(avctx, AV_LOG_ERROR, "Cannot open the h264_mp4toannexb BSF!\n");
            ret = AVERROR(ENOSYS);
            goto fail;
        }
        av_bitstream_filter_filter(ctx->bsfc, avctx, NULL, &dummy_p, &dummy_int, NULL, 0, 0);
    }

    if (avctx->extradata_size) {
        if ((status = mmal_format_extradata_alloc(format_in, avctx->extradata_size)))
            goto fail;
        format_in->extradata_size = avctx->extradata_size;
        memcpy(format_in->extradata, avctx->extradata, format_in->extradata_size);
    }

    if ((status = mmal_port_format_commit(decoder->input[0])))
        goto fail;

    decoder->input[0]->buffer_num =
        FFMAX(decoder->input[0]->buffer_num_min, 20);
    decoder->input[0]->buffer_size =
        FFMAX(decoder->input[0]->buffer_size_min, 512 * 1024);
    ctx->pool_in = mmal_pool_create(decoder->input[0]->buffer_num, 0);
    if (!ctx->pool_in) {
        ret = AVERROR(ENOMEM);
        goto fail;
    }

    if ((ret = ffmal_update_format(avctx)) < 0)
        goto fail;

    ctx->queue_decoded_frames = mmal_queue_create();
    if (!ctx->queue_decoded_frames)
        goto fail;

    decoder->input[0]->userdata = (void*)avctx;
    decoder->output[0]->userdata = (void*)avctx;
    decoder->control->userdata = (void*)avctx;

    if ((status = mmal_port_enable(decoder->control, control_port_cb)))
        goto fail;
    if ((status = mmal_port_enable(decoder->input[0], input_callback)))
        goto fail;
    if ((status = mmal_port_enable(decoder->output[0], output_callback)))
        goto fail;

    if ((status = mmal_component_enable(decoder)))
        goto fail;

    return 0;

fail:
    ffmmal_close_decoder(avctx);
    return ret < 0 ? ret : AVERROR_UNKNOWN;
}
Beispiel #11
0
/* Create Simple Video Player instance. */
SVP_T *svp_create(const char *uri, SVP_CALLBACKS_T *callbacks, const SVP_OPTS_T *opts)
{
   SVP_T *svp;
   MMAL_STATUS_T st;
   VCOS_STATUS_T vst;
   MMAL_PORT_T *reader_output = NULL;
   MMAL_COMPONENT_T *video_decode = NULL;
   MMAL_PORT_T *video_output = NULL;

   LOG_TRACE("Creating player for %s", (uri ? uri : "camera preview"));

   vcos_assert(callbacks->video_frame_cb);
   vcos_assert(callbacks->stop_cb);

   svp = vcos_calloc(1, sizeof(*svp), "svp");
   CHECK_STATUS((svp ? MMAL_SUCCESS : MMAL_ENOMEM), "Failed to allocate context");

   svp->opts = *opts;
   svp->callbacks = *callbacks;

   /* Semaphore used for synchronising buffer handling for decoded frames */
   vst = vcos_semaphore_create(&svp->sema, "svp-sem", 0);
   CHECK_STATUS((vst == VCOS_SUCCESS ? MMAL_SUCCESS : MMAL_ENOMEM), "Failed to create semaphore");
   svp->created |= SVP_CREATED_SEM;

   vst = vcos_mutex_create(&svp->mutex, "svp-mutex");
   CHECK_STATUS((vst == VCOS_SUCCESS ? MMAL_SUCCESS : MMAL_ENOMEM), "Failed to create mutex");
   svp->created |= SVP_CREATED_MUTEX;

   vst = vcos_timer_create(&svp->timer, "svp-timer", svp_timer_cb, svp);
   CHECK_STATUS((vst == VCOS_SUCCESS ? MMAL_SUCCESS : MMAL_ENOMEM), "Failed to create timer");
   svp->created |= SVP_CREATED_TIMER;

   vst = vcos_timer_create(&svp->wd_timer, "svp-wd-timer", svp_watchdog_cb, svp);
   CHECK_STATUS((vst == VCOS_SUCCESS ? MMAL_SUCCESS : MMAL_ENOMEM), "Failed to create timer");
   svp->created |= SVP_CREATED_WD_TIMER;

   /* Create components */
   svp->reader = NULL;
   svp->video_decode = NULL;
   svp->camera = NULL;
   svp->connection = NULL;

   if (uri)
   {
      /* Video from URI: setup container_reader -> video_decode */

      /* Create and set up container reader */
      st = mmal_component_create(MMAL_COMPONENT_DEFAULT_CONTAINER_READER, &svp->reader);
      CHECK_STATUS(st, "Failed to create container reader");

      st = svp_setup_reader(svp->reader, uri, &reader_output);
      if (st != MMAL_SUCCESS)
         goto error;

      st = mmal_component_enable(svp->reader);
      CHECK_STATUS(st, "Failed to enable container reader");

      st = svp_port_enable(svp, svp->reader->control, svp_bh_control_cb);
      CHECK_STATUS(st, "Failed to enable container reader control port");

      /* Create and set up video decoder */
      st = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &svp->video_decode);
      CHECK_STATUS(st, "Failed to create video decoder");

      video_decode = svp->video_decode;
      video_output = video_decode->output[0];

      st = mmal_component_enable(video_decode);
      CHECK_STATUS(st, "Failed to enable video decoder");

      st = svp_port_enable(svp, video_decode->control, svp_bh_control_cb);
      CHECK_STATUS(st, "Failed to enable video decoder control port");
   }
   else
   {
      /* Camera preview */
      MMAL_PARAMETER_CAMERA_CONFIG_T config;

      st = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &svp->camera);
      CHECK_STATUS(st, "Failed to create camera");

      st = mmal_component_enable(svp->camera);
      CHECK_STATUS(st, "Failed to enable camera");

      st = svp_port_enable(svp, svp->camera->control, svp_bh_control_cb);
      CHECK_STATUS(st, "Failed to enable camera control port");

      video_output = svp->camera->output[0]; /* Preview port */
   }

   st = mmal_port_parameter_set_boolean(video_output, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE);
   CHECK_STATUS((st == MMAL_ENOSYS ? MMAL_SUCCESS : st), "Failed to enable zero copy");

   if (uri)
   {
      /* Create connection: container_reader -> video_decoder */
      st = mmal_connection_create(&svp->connection, reader_output, video_decode->input[0],
                                  MMAL_CONNECTION_FLAG_TUNNELLING);
      CHECK_STATUS(st, "Failed to create connection");
   }

   /* Set video output port format.
    * Opaque encoding ensures we get buffer data as handles to relocatable heap. */
   video_output->format->encoding = MMAL_ENCODING_OPAQUE;

   if (!uri)
   {
      /* Set video format for camera preview */
      MMAL_VIDEO_FORMAT_T *vfmt = &video_output->format->es->video;

      CHECK_STATUS((video_output->format->type == MMAL_ES_TYPE_VIDEO) ? MMAL_SUCCESS : MMAL_EINVAL,
                   "Output port isn't video format");

      vfmt->width = SVP_CAMERA_WIDTH;
      vfmt->height = SVP_CAMERA_HEIGHT;
      vfmt->crop.x = 0;
      vfmt->crop.y = 0;
      vfmt->crop.width = vfmt->width;
      vfmt->crop.height = vfmt->height;
      vfmt->frame_rate.num = SVP_CAMERA_FRAMERATE;
      vfmt->frame_rate.den = 1;
   }

   st = mmal_port_format_commit(video_output);
   CHECK_STATUS(st, "Failed to set output port format");

   /* Finally, set buffer num/size. N.B. For container_reader/video_decode, must be after
    * connection created, in order for port format to propagate.
    * Don't enable video output port until want to produce frames. */
   video_output->buffer_num = video_output->buffer_num_recommended;
   video_output->buffer_size = video_output->buffer_size_recommended;

   /* Pool + queue to hold decoded video frames */
   svp->out_pool = mmal_port_pool_create(video_output, video_output->buffer_num,
                                         video_output->buffer_size);
   CHECK_STATUS((svp->out_pool ? MMAL_SUCCESS : MMAL_ENOMEM), "Error allocating pool");
   svp->queue = mmal_queue_create();
   CHECK_STATUS((svp ? MMAL_SUCCESS : MMAL_ENOMEM), "Error allocating queue");

   svp->video_output = video_output;

   return svp;

error:
   svp_destroy(svp);
   return NULL;
}
Beispiel #12
0
bool CMMALRenderer::init_vout(ERenderFormat format, bool opaque)
{
  CSingleLock lock(m_sharedSection);
  bool formatChanged = m_format != format || m_opaque != opaque;
  MMAL_STATUS_T status;

  CLog::Log(LOGDEBUG, "%s::%s configured:%d format %d->%d opaque %d->%d", CLASSNAME, __func__, m_bConfigured, m_format, format, m_opaque, opaque);

  if (m_bMMALConfigured && formatChanged)
    UnInitMMAL();

  if (m_bMMALConfigured || format != RENDER_FMT_MMAL)
    return true;

  m_format = format;
  m_opaque = opaque;

  /* Create video renderer */
  status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &m_vout);
  if(status != MMAL_SUCCESS)
  {
    CLog::Log(LOGERROR, "%s::%s Failed to create vout component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
    return false;
  }

  m_vout_input = m_vout->input[0];
  m_vout_input->userdata = (struct MMAL_PORT_USERDATA_T *)this;
  MMAL_ES_FORMAT_T *es_format = m_vout_input->format;

  es_format->type = MMAL_ES_TYPE_VIDEO;
  if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT709)
    es_format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT709;
  else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT601)
    es_format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT601;
  else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_240M)
    es_format->es->video.color_space = MMAL_COLOR_SPACE_SMPTE240M;

  es_format->es->video.crop.width = m_sourceWidth;
  es_format->es->video.crop.height = m_sourceHeight;
  es_format->es->video.width = m_sourceWidth;
  es_format->es->video.height = m_sourceHeight;

  es_format->encoding = m_opaque ? MMAL_ENCODING_OPAQUE : MMAL_ENCODING_I420;

  status = mmal_port_parameter_set_boolean(m_vout_input, MMAL_PARAMETER_ZERO_COPY,  MMAL_TRUE);
  if (status != MMAL_SUCCESS)
     CLog::Log(LOGERROR, "%s::%s Failed to enable zero copy mode on %s (status=%x %s)", CLASSNAME, __func__, m_vout_input->name, status, mmal_status_to_string(status));

  status = mmal_port_format_commit(m_vout_input);
  if (status != MMAL_SUCCESS)
  {
    CLog::Log(LOGERROR, "%s::%s Failed to commit vout input format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
    return false;
  }

  m_vout_input->buffer_num = std::max(m_vout_input->buffer_num_recommended, (uint32_t)m_NumYV12Buffers+(m_opaque?0:32));
  m_vout_input->buffer_size = m_vout_input->buffer_size_recommended;

  status = mmal_port_enable(m_vout_input, vout_input_port_cb_static);
  if(status != MMAL_SUCCESS)
  {
    CLog::Log(LOGERROR, "%s::%s Failed to vout enable input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
    return false;
  }

  status = mmal_component_enable(m_vout);
  if(status != MMAL_SUCCESS)
  {
    CLog::Log(LOGERROR, "%s::%s Failed to enable vout component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
    return false;
  }

  CLog::Log(LOGDEBUG, "%s::%s Created pool of size %d x %d", CLASSNAME, __func__, m_vout_input->buffer_num, m_vout_input->buffer_size);
  m_vout_input_pool = mmal_port_pool_create(m_vout_input , m_vout_input->buffer_num, m_opaque ? m_vout_input->buffer_size:0);
  if (!m_vout_input_pool)
  {
    CLog::Log(LOGERROR, "%s::%s Failed to create pool for decoder input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
    return false;
  }
  if (!CSettings::GetInstance().GetBool("videoplayer.usedisplayasclock"))
  {
    m_queue = mmal_queue_create();
    Create();
  }
  return true;
}
Beispiel #13
0
/* Registers a callback on the camera preview port to receive
 * notifications of new frames.
 * This must be called before rapitex_start and may not be called again
 * without calling raspitex_destroy first.
 *
 * @param state Pointer to the GL preview state.
 * @param port  Pointer to the camera preview port
 * @return Zero if successful.
 */
int raspitex_configure_preview_port(RASPITEX_STATE *state,
                                    MMAL_PORT_T *preview_port)
{
    MMAL_STATUS_T status;
    vcos_log_trace("%s port %p", VCOS_FUNCTION, preview_port);

    /* Enable ZERO_COPY mode on the preview port which instructs MMAL to only
     * pass the 4-byte opaque buffer handle instead of the contents of the opaque
     * buffer.
     * The opaque handle is resolved on VideoCore by the GL driver when the EGL
     * image is created.
     */
    status = mmal_port_parameter_set_boolean(preview_port,
             MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE);
    if (status != MMAL_SUCCESS)
    {
        vcos_log_error("Failed to enable zero copy on camera preview port");
        goto end;
    }

    status = mmal_port_format_commit(preview_port);
    if (status != MMAL_SUCCESS)
    {
        vcos_log_error("camera viewfinder format couldn't be set");
        goto end;
    }

    /* For GL a pool of opaque buffer handles must be allocated in the client.
     * These buffers are used to create the EGL images.
     */
    state->preview_port = preview_port;
    preview_port->buffer_num = preview_port->buffer_num_recommended;
    preview_port->buffer_size = preview_port->buffer_size_recommended;

    vcos_log_trace("Creating buffer pool for GL renderer num %d size %d",
                   preview_port->buffer_num, preview_port->buffer_size);

    /* Pool + queue to hold preview frames */
    state->preview_pool = mmal_port_pool_create(preview_port,
                          preview_port->buffer_num, preview_port->buffer_size);

    if (! state->preview_pool)
    {
        vcos_log_error("Error allocating pool");
        status = MMAL_ENOMEM;
        goto end;
    }

    /* Place filled buffers from the preview port in a queue to render */
    state->preview_queue = mmal_queue_create();
    if (! state->preview_queue)
    {
        vcos_log_error("Error allocating queue");
        status = MMAL_ENOMEM;
        goto end;
    }

    /* Enable preview port callback */
    preview_port->userdata = (struct MMAL_PORT_USERDATA_T*) state;
    status = mmal_port_enable(preview_port, preview_output_cb);
    if (status != MMAL_SUCCESS)
    {
        vcos_log_error("Failed to camera preview port");
        goto end;
    }
end:
    return (status == MMAL_SUCCESS ? 0 : -1);
}
Beispiel #14
0
void create_camera_component(int Width, int Height, int FrameRate){
	MMAL_COMPONENT_T *camera = 0;
	MMAL_ES_FORMAT_T *format;
	
	MMAL_STATUS_T status;
	
	/* Create the component */
	status = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &camera);

	if (status != MMAL_SUCCESS)	{
		printf("Failed to create camera component : error %d\n", status);
		exit(1);
	}

	if (!camera->output_num)	{
		status = MMAL_ENOSYS;
		printf("Camera doesn't have output ports\n");
		exit(1);
	}

	preview_port = camera->output[MMAL_CAMERA_PREVIEW_PORT];
	video_port = camera->output[MMAL_CAMERA_VIDEO_PORT];
	still_port = camera->output[MMAL_CAMERA_CAPTURE_PORT];
	
	// Enable the camera, and tell it its control callback function
	status = mmal_port_enable(camera->control, camera_control_callback);
	if (status != MMAL_SUCCESS)	{
		printf("Unable to enable control port : error %d\n", status);
		mmal_component_destroy(camera);
		exit(1);
	}
	
	//set camera parameters.
	MMAL_PARAMETER_CAMERA_CONFIG_T cam_config;
	cam_config.hdr = MMAL_PARAMETER_CAMERA_CONFIG;
	cam_config.hdr.size = sizeof(cam_config);
	cam_config.max_stills_w = Width;
	cam_config.max_stills_h = Height;
	cam_config.stills_yuv422 = 0;
	cam_config.one_shot_stills = 0;
	cam_config.max_preview_video_w = Width;
	cam_config.max_preview_video_h = Height;
	cam_config.num_preview_video_frames = 3;
	cam_config.stills_capture_circular_buffer_height = 0;
	cam_config.fast_preview_resume = 0;
	cam_config.use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RESET_STC;
	status = mmal_port_parameter_set(camera->control, &cam_config.hdr);

	if (status != MMAL_SUCCESS)	{
		printf("Unable to set camera parameters : error %d\n", status);
		mmal_component_destroy(camera);
		exit(1);
	}
	
	// setup preview port format - QUESTION: Needed if we aren't using preview?
	format = preview_port->format;
	format->encoding = MMAL_ENCODING_OPAQUE;
	format->encoding_variant = MMAL_ENCODING_I420;
	format->es->video.width = Width;
	format->es->video.height = Height;
	format->es->video.crop.x = 0;
	format->es->video.crop.y = 0;
	format->es->video.crop.width = Width;
	format->es->video.crop.height = Height;
	format->es->video.frame_rate.num = FrameRate;
	format->es->video.frame_rate.den = 1;
	status = mmal_port_format_commit(preview_port);
	if (status != MMAL_SUCCESS)
	{
		printf("Couldn't set preview port format : error %d\n", status);
		mmal_component_destroy(camera);
		exit(1);
	}

	//setup video port format
	format = video_port->format;
	format->encoding = MMAL_ENCODING_I420;
	format->encoding_variant = MMAL_ENCODING_I420;
	format->es->video.width = Width;
	format->es->video.height = Height;
	format->es->video.crop.x = 0;
	format->es->video.crop.y = 0;
	format->es->video.crop.width = Width;
	format->es->video.crop.height = Height;
	format->es->video.frame_rate.num = FrameRate;
	format->es->video.frame_rate.den = 1;
	status = mmal_port_format_commit(video_port);
	if (status != MMAL_SUCCESS)
	{
		printf("Couldn't set video port format : error %d\n", status);
		mmal_component_destroy(camera);
		exit(1);
	}
	
	//setup still port format
	format = still_port->format;
	format->encoding = MMAL_ENCODING_OPAQUE;
	format->encoding_variant = MMAL_ENCODING_I420;
	format->es->video.width = Width;
	format->es->video.height = Height;
	format->es->video.crop.x = 0;
	format->es->video.crop.y = 0;
	format->es->video.crop.width = Width;
	format->es->video.crop.height = Height;
	format->es->video.frame_rate.num = 1;
	format->es->video.frame_rate.den = 1;
	status = mmal_port_format_commit(still_port);
	if (status != MMAL_SUCCESS)
	{
		printf("Couldn't set still port format : error %d\n", status);
		mmal_component_destroy(camera);
		exit(1);
	}
	
	status = mmal_port_parameter_set_boolean(preview_port,
	MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE);
	if (status != MMAL_SUCCESS)
	{
		printf("Failed to enable zero copy on camera video port\n");
		exit(1);
	}
	
	status = mmal_port_format_commit(preview_port);
	if (status != MMAL_SUCCESS)
	{
		printf("camera format couldn't be set\n");
		exit(1);
	}
	
	/* For GL a pool of opaque buffer handles must be allocated in the client.
	* These buffers are used to create the EGL images.
	*/
	preview_port->buffer_num = 3;
	preview_port->buffer_size = preview_port->buffer_size_recommended;

	/* Pool + queue to hold preview frames */
	video_pool = mmal_port_pool_create(preview_port,preview_port->buffer_num,preview_port->buffer_size);
	if (!video_pool)
	{
		printf("Error allocating camera video pool. Buffer num: %d Buffer size: %d\n", preview_port->buffer_num, preview_port->buffer_size);
		status = MMAL_ENOMEM;
		exit(1);
	}
	printf("Allocated %d MMAL buffers of size %d.\n", preview_port->buffer_num, preview_port->buffer_size);

	/* Place filled buffers from the preview port in a queue to render */
	video_queue = mmal_queue_create();
	if (!video_queue)
	{
		printf("Error allocating video buffer queue\n");
		status = MMAL_ENOMEM;
		exit(1);
	}

	/* Enable video port callback */
	//port->userdata = (struct MMAL_PORT_USERDATA_T *)this;
	status = mmal_port_enable(preview_port, video_output_callback);
	if (status != MMAL_SUCCESS)
	{
		printf("Failed to enable video port\n");
		exit(1);
	}
	
	// Set up the camera_parameters to default
	raspicamcontrol_set_defaults(&cameraParameters);
	//apply all camera parameters
	raspicamcontrol_set_all_parameters(camera, &cameraParameters);

	//enable the camera
	status = mmal_component_enable(camera);
	if (status != MMAL_SUCCESS)
	{
		printf("Couldn't enable camera\n\n");
		mmal_component_destroy(camera);
		exit(1);
	}
	
	//send all the buffers in our pool to the video port ready for use
	{
		int num = mmal_queue_length(video_pool->queue);
		int q;
		for (q=0;q<num;q++)
		{
			MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(video_pool->queue);
			if (!buffer)
			{
				printf("Unable to get a required buffer %d from pool queue\n\n", q);
				exit(1);
			}
			else if (mmal_port_send_buffer(preview_port, buffer)!= MMAL_SUCCESS)
			{
				printf("Unable to send a buffer to port (%d)\n\n", q);
				exit(1);
			}
		}
	}
	
	/*
	//begin capture
	if (mmal_port_parameter_set_boolean(preview_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS)
	{
		printf("Failed to start capture\n\n");
		exit(1);
	}
	*/
	
	printf("Camera initialized.\n");
	
	
	
	//Setup the camera's textures and EGL images.
	glGenTextures(1, &cam_ytex);
	glGenTextures(1, &cam_utex);
	glGenTextures(1, &cam_vtex);
	
	return;
}