int mmal_util_rgb_order_fixed(MMAL_PORT_T *port) { int new_fw = 0; //Firmware support of RGB24 vs BGR24 colour ordering from camera //and video splitter components has been corrected as of June 2016. //New firmwares always report MMAL_ENCODING_RGB24 before BGR24, and //that is the format we want. //Old firmware reported BGR24 first, and also returned an error on //the still port on querying MMAL_PARAMETER_SUPPORTED_ENCODINGS. MMAL_SUPPORTED_ENCODINGS_T sup_encodings = {{MMAL_PARAMETER_SUPPORTED_ENCODINGS, sizeof(sup_encodings)}, {0}}; if (mmal_port_parameter_get(port, &sup_encodings.header) == MMAL_SUCCESS) { int i; int num_encodings = (sup_encodings.header.size - sizeof(sup_encodings.header)) / sizeof(sup_encodings.encodings[0]); for (i=0; i<num_encodings; i++) { if (sup_encodings.encodings[i] == MMAL_ENCODING_BGR24) { //Found BGR24 first - old firmware. break; } if (sup_encodings.encodings[i] == MMAL_ENCODING_RGB24) { //Found RGB24 first - new firmware, so use RGB24. new_fw = 1; } } } return new_fw; }
bool CMMALVideo::change_dec_output_format() { MMAL_STATUS_T status; if (g_advancedSettings.CanLogComponent(LOGVIDEO)) CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T interlace_type = {{ MMAL_PARAMETER_VIDEO_INTERLACE_TYPE, sizeof( interlace_type )}}; status = mmal_port_parameter_get( m_dec_output, &interlace_type.hdr ); if (status == MMAL_SUCCESS) { if (m_interlace_mode != interlace_type.eMode) { if (g_advancedSettings.CanLogComponent(LOGVIDEO)) CLog::Log(LOGDEBUG, "%s::%s Interlace mode %d->%d", CLASSNAME, __func__, m_interlace_mode, interlace_type.eMode); m_interlace_mode = interlace_type.eMode; } } else CLog::Log(LOGERROR, "%s::%s Failed to query interlace type on %s (status=%x %s)", CLASSNAME, __func__, m_dec_output->name, status, mmal_status_to_string(status)); // todo: if we don't disable/enable we can do this from callback mmal_format_copy(m_dec_output->format, m_es_format); status = mmal_port_format_commit(m_dec_output); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to commit decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } return true; }
MMAL_PARAMETER_HEADER_T *mmal_port_parameter_alloc_get(MMAL_PORT_T *port, uint32_t id, uint32_t size, MMAL_STATUS_T *p_status) { MMAL_PARAMETER_HEADER_T *param = NULL; MMAL_STATUS_T status = MMAL_ENOSYS; if (size < sizeof(MMAL_PARAMETER_HEADER_T)) size = sizeof(MMAL_PARAMETER_HEADER_T); if ((param = vcos_calloc(1, size, "mmal_port_param_get")) == NULL) { status = MMAL_ENOMEM; goto error; } param->id = id; param->size = size; if ((status = mmal_port_parameter_get(port, param)) == MMAL_ENOSPC) { /* We need to reallocate to get enough space for all parameter data */ size = param->size; vcos_free(param); if ((param = vcos_calloc(1, size, "mmal_port_param_get")) == NULL) { status = MMAL_ENOMEM; goto error; } /* Now retrieve it again */ param->id = id; param->size = size; status = mmal_port_parameter_get(port, param); } if (status != MMAL_SUCCESS) goto error; end: if (p_status) *p_status = status; return param; error: if (param) vcos_free(param); param = NULL; goto end; }
MMAL_STATUS_T get_camera_flash_type(MMAL_COMPONENT_T *camera, MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_T *value){ if (!camera) return MMAL_ENOTREADY; MMAL_PARAMETER_FLASH_SELECT_T param = {{MMAL_PARAMETER_FLASH_SELECT , sizeof(param)}, 0}; MMAL_STATUS_T status; status = mmal_port_parameter_get(camera->control, ¶m.hdr); *value = param.flash_type; return status; }
MMAL_STATUS_T get_camera_metering_mode(MMAL_COMPONENT_T *camera, MMAL_PARAM_EXPOSUREMETERINGMODE_T *value){ if (!camera) return MMAL_ENOTREADY; MMAL_PARAMETER_EXPOSUREMETERINGMODE_T param = {{MMAL_PARAMETER_EXP_METERING_MODE, sizeof(param)}, 0}; MMAL_STATUS_T status; status = mmal_port_parameter_get(camera->control, ¶m.hdr); *value = param.value; return status; }
MMAL_STATUS_T get_camera_flash_mode(MMAL_COMPONENT_T *camera, MMAL_PARAM_FLASH_T *value){ if (!camera) return MMAL_ENOTREADY; MMAL_PARAMETER_FLASH_T param = {{MMAL_PARAMETER_FLASH, sizeof(param)}, 0}; MMAL_STATUS_T status; status = mmal_port_parameter_get(camera->control, ¶m.hdr); *value = param.value; return status; }
MMAL_STATUS_T get_camera_image_fx(MMAL_COMPONENT_T *camera, MMAL_PARAM_IMAGEFX_T *value){ if (!camera) return MMAL_ENOTREADY; MMAL_PARAMETER_IMAGEFX_T param = {{MMAL_PARAMETER_IMAGE_EFFECT, sizeof(param)}, 0}; MMAL_STATUS_T status; status = mmal_port_parameter_get(camera->control, ¶m.hdr); *value = param.value; return status; }
MMAL_STATUS_T get_camera_flips(MMAL_COMPONENT_T *camera, MMAL_PARAM_MIRROR_T *value){ if (!camera) return MMAL_ENOTREADY; MMAL_PARAMETER_AWBMODE_T param = {{MMAL_PARAMETER_AWB_MODE, sizeof(param)}, 0}; MMAL_STATUS_T status = MMAL_SUCCESS; uint8_t port = 0; for (port=0; port<3; port++){ status |= mmal_port_parameter_get(camera->output[port], ¶m.hdr); } *value = param.value; return status; }
static OMX_ERRORTYPE mmalomx_get_video_param(MMALOMX_PORT_T *port, uint32_t *profile, uint32_t *level, uint32_t *intraperiod) { MMAL_PARAMETER_VIDEO_PROFILE_T mmal_param = {{MMAL_PARAMETER_PROFILE, sizeof(mmal_param)}, {{(MMAL_VIDEO_PROFILE_T)0, (MMAL_VIDEO_LEVEL_T)0}}}; *profile = *level = *intraperiod = 0; mmal_port_parameter_get_uint32(port->mmal, MMAL_PARAMETER_INTRAPERIOD, intraperiod); if (mmal_port_parameter_get(port->mmal, &mmal_param.hdr) == MMAL_SUCCESS) { *profile = mmalil_video_profile_to_omx(mmal_param.profile[0].profile); *level = mmalil_video_level_to_omx(mmal_param.profile[0].level); } return OMX_ErrorNone; }
static OMX_ERRORTYPE mmalomx_parameter_get_xlat(MMALOMX_COMPONENT_T *component, OMX_INDEXTYPE nParamIndex, OMX_PTR pParam) { const MMALOMX_PARAM_TRANSLATION_T *xlat = mmalomx_find_parameter_from_omx_id(nParamIndex); MMALOMX_PARAM_OMX_HEADER_T *omx_header = (MMALOMX_PARAM_OMX_HEADER_T *)pParam; MMALOMX_PARAM_MMAL_GENERIC_T mmal_generic; MMAL_PARAMETER_HEADER_T *mmal_header = &mmal_generic.header; MMAL_PORT_T *mmal_port = component->mmal->control; MMAL_STATUS_T status = MMAL_SUCCESS; if (!xlat) return OMX_ErrorNotImplemented; if (!xlat->portless) { if (omx_header->nSize < sizeof(*omx_header)) return OMX_ErrorBadParameter; if (omx_header->nPortIndex >= component->ports_num) return OMX_ErrorBadPortIndex; mmal_port = component->ports[omx_header->nPortIndex].mmal; } if (omx_header->nSize < xlat->omx_size) return OMX_ErrorBadParameter; /* Handle the direct case first */ if (xlat->type == MMALOMX_PARAM_TRANSLATION_TYPE_DIRECT) { OMX_U32 size; mmal_header = (MMAL_PARAMETER_HEADER_T *)(((uint8_t *)pParam) + (xlat->portless ? 0 : 4)); mmal_generic.header = *mmal_header; mmal_header->size = omx_header->nSize - (xlat->portless ? 0 : 4); mmal_header->id = xlat->mmal_id; status = mmal_port_parameter_get(mmal_port, mmal_header); *mmal_header = mmal_generic.header; size = mmal_header->size + (xlat->portless ? 0 : 4); omx_header->nSize = size; return mmalil_error_to_omx(status); } if (xlat->fn.custom) { return mmalil_error_to_omx(xlat->fn.custom(MMALOMX_PARAM_MAPPING_TO_OMX, xlat, mmal_header, pParam, mmal_port)); } if (xlat->fn.list) { OMX_U32 index, elements; mmal_header = mmal_port_parameter_alloc_get(mmal_port, xlat->mmal_id, 10*xlat->mmal_size, &status); if (!mmal_header) return OMX_ErrorInsufficientResources; /* Check we're not requesting too much */ index = *(OMX_U32 *)(((uint8_t *)pParam) + xlat->xlat_enum_num); elements = (mmal_header->size - sizeof(MMAL_PARAMETER_HEADER_T)) / (xlat->mmal_size - sizeof(MMAL_PARAMETER_HEADER_T)); if (index >= elements) { vcos_free(mmal_header); return OMX_ErrorNoMore; } status = xlat->fn.list(MMALOMX_PARAM_MAPPING_TO_OMX, xlat, index, mmal_header, pParam, mmal_port); vcos_free(mmal_header); return mmalil_error_to_omx(status); } if (!xlat->fn.generic && !xlat->fn.simple) { // FIXME return OMX_ErrorNotImplemented; } // FIXME: check size of mmal_generic is sufficient if (sizeof(mmal_generic) < xlat->mmal_size) return OMX_ErrorBadParameter; mmal_header->size = xlat->mmal_size; mmal_header->id = xlat->mmal_id; if (xlat->double_translation) { if (xlat->fn.generic) status = xlat->fn.generic(MMALOMX_PARAM_MAPPING_TO_MMAL, xlat, mmal_header, pParam, mmal_port); else status = xlat->fn.simple(MMALOMX_PARAM_MAPPING_TO_MMAL, mmal_header, pParam); } if (status != MMAL_SUCCESS) goto error; status = mmal_port_parameter_get(mmal_port, mmal_header); if (status != MMAL_SUCCESS) goto error; if (xlat->fn.generic) status = xlat->fn.generic(MMALOMX_PARAM_MAPPING_TO_OMX, xlat, mmal_header, pParam, mmal_port); else status = xlat->fn.simple(MMALOMX_PARAM_MAPPING_TO_OMX, mmal_header, pParam); error: return mmalil_error_to_omx(status); }
free(dmx_region); } static void maintain_phase_sync(vout_display_t *vd) { MMAL_PARAMETER_VIDEO_RENDER_STATS_T render_stats = { .hdr = { MMAL_PARAMETER_VIDEO_RENDER_STATS, sizeof(render_stats) }, }; int32_t frame_duration = 1000000 / ((double)vd->source.i_frame_rate / vd->source.i_frame_rate_base); vout_display_sys_t *sys = vd->sys; int32_t phase_offset; MMAL_STATUS_T status; status = mmal_port_parameter_get(sys->input, &render_stats.hdr); if (status != MMAL_SUCCESS) { msg_Err(vd, "Failed to read render stats on control port %s (status=%"PRIx32" %s)", sys->input->name, status, mmal_status_to_string(status)); return; } if (render_stats.valid) { #ifndef NDEBUG msg_Dbg(vd, "render_stats: match: %u, period: %u ms, phase: %u ms, hvs: %u", render_stats.match, render_stats.period / 1000, render_stats.phase / 1000, render_stats.hvs_status); #endif if (render_stats.phase > 0.1 * frame_duration && render_stats.phase < 0.75 * frame_duration)
MMAL_STATUS_T get_camera_colour_fx(MMAL_COMPONENT_T *camera, MMAL_PARAMETER_COLOURFX_T *value){ if (!camera) return MMAL_ENOTREADY; return mmal_port_parameter_get(camera->control, &(value->hdr)); }
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; MMAL_BOOL_T eos_sent = MMAL_FALSE, eos_received = MMAL_FALSE; unsigned int count; if (argc < 2) { fprintf(stderr, "invalid arguments\n"); return -1; } 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"); /* Enable control port so we can receive events from the component */ decoder->control->userdata = (void *)&context; status = mmal_port_enable(decoder->control, control_callback); CHECK_STATUS(status, "failed to enable control port"); /* Get statistics on the input port */ MMAL_PARAMETER_CORE_STATISTICS_T stats = {{0}}; stats.hdr.id = MMAL_PARAMETER_CORE_STATISTICS; stats.hdr.size = sizeof(MMAL_PARAMETER_CORE_STATISTICS_T); status = mmal_port_parameter_get(decoder->input[0], &stats.hdr); CHECK_STATUS(status, "failed to get stats"); fprintf(stderr, "stats: %i, %i", stats.stats.buffer_count, stats.stats.max_delay); /* Set the zero-copy parameter on the input port */ MMAL_PARAMETER_BOOLEAN_T zc = {{MMAL_PARAMETER_ZERO_COPY, sizeof(zc)}, MMAL_TRUE}; status = mmal_port_parameter_set(decoder->input[0], &zc.hdr); fprintf(stderr, "status: %i\n", status); /* Set the zero-copy parameter on the output port */ status = mmal_port_parameter_set_boolean(decoder->output[0], MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE); fprintf(stderr, "status: %i\n", status); /* 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"); /* Our decoder can do internal colour conversion, ask for a conversion to RGB565 */ MMAL_ES_FORMAT_T *format_out = decoder->output[0]->format; format_out->encoding = MMAL_ENCODING_RGB16; status = mmal_port_format_commit(decoder->output[0]); CHECK_STATUS(status, "failed to commit format"); /* Display the output port 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; !eos_received && 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); /* Check for errors */ if (context.status != MMAL_SUCCESS) break; /* Send data to decode to the input port of the video decoder */ if (!eos_sent && (buffer = mmal_queue_get(pool_in->queue)) != NULL) { SOURCE_READ_DATA_INTO_BUFFER(buffer); if(!buffer->length) eos_sent = MMAL_TRUE; buffer->flags = buffer->length ? 0 : MMAL_BUFFER_HEADER_FLAG_EOS; buffer->pts = buffer->dts = MMAL_TIME_UNKNOWN; 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. */ eos_received = buffer->flags & MMAL_BUFFER_HEADER_FLAG_EOS; if (buffer->cmd) fprintf(stderr, "received event %4.4s", (char *)&buffer->cmd); else fprintf(stderr, "decoded frame (flags %x)\n", buffer->flags); 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; }
MMAL_STATUS_T get_camera_info(MMAL_COMPONENT_T *camera, MMAL_PARAMETER_CAMERA_INFO_T *value){ if (!camera) return MMAL_ENOTREADY; return mmal_port_parameter_get(camera->control, &(value->hdr)); }
static int change_output_format(decoder_t *dec) { MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T interlace_type; decoder_sys_t *sys = dec->p_sys; MMAL_STATUS_T status; int pool_size; int ret = 0; if (atomic_load(&sys->started)) { mmal_format_full_copy(sys->output->format, sys->output_format); status = mmal_port_format_commit(sys->output); if (status != MMAL_SUCCESS) { msg_Err(dec, "Failed to commit output format (status=%"PRIx32" %s)", status, mmal_status_to_string(status)); ret = -1; goto port_reset; } goto apply_fmt; } port_reset: msg_Dbg(dec, "%s: Do full port reset", __func__); status = mmal_port_disable(sys->output); if (status != MMAL_SUCCESS) { msg_Err(dec, "Failed to disable output port (status=%"PRIx32" %s)", status, mmal_status_to_string(status)); ret = -1; goto out; } mmal_format_full_copy(sys->output->format, sys->output_format); status = mmal_port_format_commit(sys->output); if (status != MMAL_SUCCESS) { msg_Err(dec, "Failed to commit output format (status=%"PRIx32" %s)", status, mmal_status_to_string(status)); ret = -1; goto out; } if (sys->opaque) { sys->output->buffer_num = NUM_ACTUAL_OPAQUE_BUFFERS; pool_size = NUM_DECODER_BUFFER_HEADERS; } else { sys->output->buffer_num = __MAX(sys->output->buffer_num_recommended, MIN_NUM_BUFFERS_IN_TRANSIT); pool_size = sys->output->buffer_num; } sys->output->buffer_size = sys->output->buffer_size_recommended; status = mmal_port_enable(sys->output, output_port_cb); if (status != MMAL_SUCCESS) { msg_Err(dec, "Failed to enable output port (status=%"PRIx32" %s)", status, mmal_status_to_string(status)); ret = -1; goto out; } if (!atomic_load(&sys->started)) { if (!sys->opaque) { sys->output_pool = mmal_port_pool_create(sys->output, pool_size, 0); msg_Dbg(dec, "Created output pool with %d pictures", sys->output_pool->headers_num); } atomic_store(&sys->started, true); /* we need one picture from vout for each buffer header on the output * port */ dec->i_extra_picture_buffers = pool_size; /* remove what VLC core reserves as it is part of the pool_size * already */ if (dec->fmt_in.i_codec == VLC_CODEC_H264) dec->i_extra_picture_buffers -= 19; else dec->i_extra_picture_buffers -= 3; msg_Dbg(dec, "Request %d extra pictures", dec->i_extra_picture_buffers); } apply_fmt: dec->fmt_out.video.i_width = sys->output->format->es->video.width; dec->fmt_out.video.i_height = sys->output->format->es->video.height; dec->fmt_out.video.i_x_offset = sys->output->format->es->video.crop.x; dec->fmt_out.video.i_y_offset = sys->output->format->es->video.crop.y; dec->fmt_out.video.i_visible_width = sys->output->format->es->video.crop.width; dec->fmt_out.video.i_visible_height = sys->output->format->es->video.crop.height; dec->fmt_out.video.i_sar_num = sys->output->format->es->video.par.num; dec->fmt_out.video.i_sar_den = sys->output->format->es->video.par.den; dec->fmt_out.video.i_frame_rate = sys->output->format->es->video.frame_rate.num; dec->fmt_out.video.i_frame_rate_base = sys->output->format->es->video.frame_rate.den; /* Query interlaced type */ interlace_type.hdr.id = MMAL_PARAMETER_VIDEO_INTERLACE_TYPE; interlace_type.hdr.size = sizeof(MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T); status = mmal_port_parameter_get(sys->output, &interlace_type.hdr); if (status != MMAL_SUCCESS) { msg_Warn(dec, "Failed to query interlace type from decoder output port (status=%"PRIx32" %s)", status, mmal_status_to_string(status)); } else { sys->b_progressive = (interlace_type.eMode == MMAL_InterlaceProgressive); sys->b_top_field_first = sys->b_progressive ? true : (interlace_type.eMode == MMAL_InterlaceFieldsInterleavedUpperFirst); msg_Dbg(dec, "Detected %s%s video (%d)", sys->b_progressive ? "progressive" : "interlaced", sys->b_progressive ? "" : (sys->b_top_field_first ? " tff" : " bff"), interlace_type.eMode); } out: mmal_format_free(sys->output_format); sys->output_format = NULL; return ret; }
static int ffmal_update_format(AVCodecContext *avctx) { MMALDecodeContext *ctx = avctx->priv_data; MMAL_STATUS_T status; int ret = 0; MMAL_COMPONENT_T *decoder = ctx->decoder; MMAL_ES_FORMAT_T *format_out = decoder->output[0]->format; MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T interlace_type; ffmmal_poolref_unref(ctx->pool_out); if (!(ctx->pool_out = av_mallocz(sizeof(*ctx->pool_out)))) { ret = AVERROR(ENOMEM); goto fail; } ctx->pool_out->refcount = 1; if (!format_out) goto fail; if ((status = mmal_port_parameter_set_uint32(decoder->output[0], MMAL_PARAMETER_EXTRA_BUFFERS, ctx->extra_buffers))) goto fail; if ((status = mmal_port_parameter_set_boolean(decoder->output[0], MMAL_PARAMETER_VIDEO_INTERPOLATE_TIMESTAMPS, 0))) goto fail; if (avctx->pix_fmt == AV_PIX_FMT_MMAL) { format_out->encoding = MMAL_ENCODING_OPAQUE; } else { format_out->encoding_variant = format_out->encoding = MMAL_ENCODING_I420; } if ((status = mmal_port_format_commit(decoder->output[0]))) goto fail; interlace_type.hdr.id = MMAL_PARAMETER_VIDEO_INTERLACE_TYPE; interlace_type.hdr.size = sizeof(MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T); status = mmal_port_parameter_get(decoder->output[0], &interlace_type.hdr); if (status != MMAL_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Cannot read MMAL interlace information!\n"); } else { ctx->interlaced_frame = (interlace_type.eMode != MMAL_InterlaceProgressive); ctx->top_field_first = (interlace_type.eMode == MMAL_InterlaceFieldsInterleavedUpperFirst); } if ((ret = ff_set_dimensions(avctx, format_out->es->video.crop.x + format_out->es->video.crop.width, format_out->es->video.crop.y + format_out->es->video.crop.height)) < 0) goto fail; if (format_out->es->video.par.num && format_out->es->video.par.den) { avctx->sample_aspect_ratio.num = format_out->es->video.par.num; avctx->sample_aspect_ratio.den = format_out->es->video.par.den; } if (format_out->es->video.frame_rate.num && format_out->es->video.frame_rate.den) { avctx->framerate.num = format_out->es->video.frame_rate.num; avctx->framerate.den = format_out->es->video.frame_rate.den; } avctx->colorspace = ffmmal_csp_to_av_csp(format_out->es->video.color_space); decoder->output[0]->buffer_size = FFMAX(decoder->output[0]->buffer_size_min, decoder->output[0]->buffer_size_recommended); decoder->output[0]->buffer_num = FFMAX(decoder->output[0]->buffer_num_min, decoder->output[0]->buffer_num_recommended) + ctx->extra_buffers; ctx->pool_out->pool = mmal_pool_create(decoder->output[0]->buffer_num, decoder->output[0]->buffer_size); if (!ctx->pool_out->pool) { ret = AVERROR(ENOMEM); goto fail; } return 0; fail: return ret < 0 ? ret : AVERROR_UNKNOWN; }
/** * Reset the encoder component, set up its ports * * @param state Pointer to state control struct * * @return MMAL_SUCCESS if all OK, something else otherwise * */ MMAL_STATUS_T reset_encoder_component(RASPIVID_STATE *state) { MMAL_COMPONENT_T *encoder = 0; MMAL_PORT_T *encoder_input = NULL, *encoder_output = NULL; MMAL_STATUS_T status; MMAL_POOL_T *pool; // Get the encoder component if( state->encoder_component == NULL ) { vcos_log_error("Unable to get video encoder component"); goto error; } else { encoder = state->encoder_component; } #ifdef __NOT_REQURED__ if (!encoder->input_num || !encoder->output_num) { status = MMAL_ENOSYS; vcos_log_error("Video encoder doesn't have input/output ports"); goto error; } encoder_input = encoder->input[0]; encoder_output = encoder->output[0]; // We want same format on input and output mmal_format_copy(encoder_output->format, encoder_input->format); // Only supporting H264 at the moment encoder_output->format->encoding = state->encoding; encoder_output->format->bitrate = state->bitrate; if (state->encoding == MMAL_ENCODING_H264) encoder_output->buffer_size = encoder_output->buffer_size_recommended; else encoder_output->buffer_size = 256<<10; if (encoder_output->buffer_size < encoder_output->buffer_size_min) encoder_output->buffer_size = encoder_output->buffer_size_min; encoder_output->buffer_num = encoder_output->buffer_num_recommended; if (encoder_output->buffer_num < encoder_output->buffer_num_min) encoder_output->buffer_num = encoder_output->buffer_num_min; // We need to set the frame rate on output to 0, to ensure it gets // updated correctly from the input framerate when port connected encoder_output->format->es->video.frame_rate.num = 0; encoder_output->format->es->video.frame_rate.den = 1; // Commit the port changes to the output port status = mmal_port_format_commit(encoder_output); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set format on video encoder output port"); goto error; } if (state->encoding == MMAL_ENCODING_H264 && state->intraperiod != -1) { MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_INTRAPERIOD, sizeof(param)}, state->intraperiod}; status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set intraperiod"); goto error; } } if (state->encoding == MMAL_ENCODING_H264 && state->quantisationParameter) { MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT, sizeof(param)}, state->quantisationInitialParameter}; status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set initial QP"); goto error; } MMAL_PARAMETER_UINT32_T param2 = {{ MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT, sizeof(param)}, state->quantisationMinParameter}; status = mmal_port_parameter_set(encoder_output, ¶m2.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set min QP"); goto error; } MMAL_PARAMETER_UINT32_T param3 = {{ MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT, sizeof(param)}, state->quantisationMaxParameter}; status = mmal_port_parameter_set(encoder_output, ¶m3.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set max QP"); goto error; } } if (state->encoding == MMAL_ENCODING_H264) { MMAL_PARAMETER_VIDEO_PROFILE_T param; param.hdr.id = MMAL_PARAMETER_PROFILE; param.hdr.size = sizeof(param); param.profile[0].profile = state->profile; param.profile[0].level = MMAL_VIDEO_LEVEL_H264_4; // This is the only value supported status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set H264 profile"); goto error; } } if (mmal_port_parameter_set_boolean(encoder_input, MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, state->immutableInput) != MMAL_SUCCESS) { vcos_log_error("Unable to set immutable input flag"); // Continue rather than abort.. } //set INLINE HEADER flag to generate SPS and PPS for every IDR if requested if (mmal_port_parameter_set_boolean(encoder_output, MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER, state->bInlineHeaders) != MMAL_SUCCESS) { vcos_log_error("failed to set INLINE HEADER FLAG parameters"); // Continue rather than abort.. } //set Encode SPS Timing if (mmal_port_parameter_set_boolean(encoder_output, MMAL_PARAMETER_VIDEO_ENCODE_SPS_TIMING, MMAL_TRUE) != MMAL_SUCCESS) { vcos_log_error("failed to set SPS TIMING HEADER FLAG parameters"); // Continue rather than abort.. } // set Minimise Fragmentation if (mmal_port_parameter_set_boolean(encoder_output, MMAL_PARAMETER_MINIMISE_FRAGMENTATION, MMAL_FALSE) != MMAL_SUCCESS) { vcos_log_error("failed to set SPS TIMING HEADER FLAG parameters"); // Continue rather than abort.. } // Adaptive intra refresh settings if (state->encoding == MMAL_ENCODING_H264 && state->intra_refresh_type != -1) { MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T param; param.hdr.id = MMAL_PARAMETER_VIDEO_INTRA_REFRESH; param.hdr.size = sizeof(param); // Get first so we don't overwrite anything unexpectedly status = mmal_port_parameter_get(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_warn("Unable to get existing H264 intra-refresh values. Please update your firmware"); // Set some defaults, don't just pass random stack data param.air_mbs = param.air_ref = param.cir_mbs = param.pir_mbs = 0; } param.refresh_mode = state->intra_refresh_type; //if (state->intra_refresh_type == MMAL_VIDEO_INTRA_REFRESH_CYCLIC_MROWS) // param.cir_mbs = 10; status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set H264 intra-refresh values"); goto error; } } #endif /* NOT_REQUIRED */ // Enable component status = mmal_component_enable(encoder); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to enable video encoder component"); goto error; } #ifdef __NOT_REQURED__ /* Create pool of buffer headers for the output port to consume */ pool = mmal_port_pool_create(encoder_output, encoder_output->buffer_num, encoder_output->buffer_size); if (!pool) { vcos_log_error("Failed to create buffer header pool for encoder output port %s", encoder_output->name); } state->encoder_pool = pool; state->encoder_component = encoder; #endif /* NOT_REQUIRED */ return status; error: if (encoder) mmal_component_destroy(encoder); state->encoder_component = NULL; return status; }