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; 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; 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; } 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; }
bool CMMALRenderer::init_vout(MMAL_ES_FORMAT_T *format) { MMAL_STATUS_T status; CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); /* 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->control->userdata = (struct MMAL_PORT_USERDATA_T *)this; status = mmal_port_enable(m_vout->control, vout_control_port_cb); if(status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to enable vout control port (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_format_full_copy(m_vout_input->format, format); 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_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; } if (m_format == RENDER_FMT_YUV420P) { m_vout_input_pool = mmal_pool_create(m_vout_input->buffer_num, m_vout_input->buffer_size); 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; } } return true; }
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; }
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; }
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; }
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; }
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; }
bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVideoPtr myself) { if (g_advancedSettings.CanLogComponent(LOGVIDEO)) CLog::Log(LOGDEBUG, "%s::%s usemmal:%d software:%d %dx%d", CLASSNAME, __func__, CSettings::Get().GetBool("videoplayer.usemmal"), hints.software, hints.width, hints.height); // we always qualify even if DVDFactoryCodec does this too. if (!CSettings::Get().GetBool("videoplayer.usemmal") || hints.software) return false; m_hints = hints; MMAL_STATUS_T status; MMAL_PARAMETER_BOOLEAN_T error_concealment; m_myself = myself; m_decoded_width = hints.width; m_decoded_height = hints.height; // use aspect in stream if available if (m_hints.forced_aspect) m_aspect_ratio = m_hints.aspect; else m_aspect_ratio = 0.0; switch (hints.codec) { case AV_CODEC_ID_H264: // H.264 m_codingType = MMAL_ENCODING_H264; m_pFormatName = "mmal-h264"; break; case AV_CODEC_ID_H263: case AV_CODEC_ID_MPEG4: // MPEG-4, DivX 4/5 and Xvid compatible m_codingType = MMAL_ENCODING_MP4V; m_pFormatName = "mmal-mpeg4"; break; case AV_CODEC_ID_MPEG1VIDEO: case AV_CODEC_ID_MPEG2VIDEO: // MPEG-2 m_codingType = MMAL_ENCODING_MP2V; m_pFormatName = "mmal-mpeg2"; break; case AV_CODEC_ID_VP6: // this form is encoded upside down // fall through case AV_CODEC_ID_VP6F: case AV_CODEC_ID_VP6A: // VP6 m_codingType = MMAL_ENCODING_VP6; m_pFormatName = "mmal-vp6"; break; case AV_CODEC_ID_VP8: // VP8 m_codingType = MMAL_ENCODING_VP8; m_pFormatName = "mmal-vp8"; break; case AV_CODEC_ID_THEORA: // theora m_codingType = MMAL_ENCODING_THEORA; m_pFormatName = "mmal-theora"; break; case AV_CODEC_ID_MJPEG: case AV_CODEC_ID_MJPEGB: // mjpg m_codingType = MMAL_ENCODING_MJPEG; m_pFormatName = "mmal-mjpg"; break; case AV_CODEC_ID_VC1: case AV_CODEC_ID_WMV3: // VC-1, WMV9 m_codingType = MMAL_ENCODING_WVC1; m_pFormatName = "mmal-vc1"; break; default: CLog::Log(LOGERROR, "%s::%s : Video codec unknown: %x", CLASSNAME, __func__, hints.codec); return false; break; } if ( (m_codingType == MMAL_ENCODING_MP2V && !g_RBP.GetCodecMpg2() ) || (m_codingType == MMAL_ENCODING_WVC1 && !g_RBP.GetCodecWvc1() ) ) { CLog::Log(LOGWARNING, "%s::%s Codec %s is not supported", CLASSNAME, __func__, m_pFormatName); return false; } // initialize mmal. status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &m_dec); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to create MMAL decoder component %s (status=%x %s)", CLASSNAME, __func__, MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, status, mmal_status_to_string(status)); return false; } m_dec->control->userdata = (struct MMAL_PORT_USERDATA_T *)this; status = mmal_port_enable(m_dec->control, dec_control_port_cb_static); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to enable decoder control port %s (status=%x %s)", CLASSNAME, __func__, MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, status, mmal_status_to_string(status)); return false; } m_dec_input = m_dec->input[0]; m_dec_input->format->type = MMAL_ES_TYPE_VIDEO; m_dec_input->format->encoding = m_codingType; if (m_hints.width && m_hints.height) { m_dec_input->format->es->video.crop.width = m_hints.width; m_dec_input->format->es->video.crop.height = m_hints.height; m_dec_input->format->es->video.width = ALIGN_UP(m_hints.width, 32); m_dec_input->format->es->video.height = ALIGN_UP(m_hints.height, 16); } m_dec_input->format->flags |= MMAL_ES_FORMAT_FLAG_FRAMED; error_concealment.hdr.id = MMAL_PARAMETER_VIDEO_DECODE_ERROR_CONCEALMENT; error_concealment.hdr.size = sizeof(MMAL_PARAMETER_BOOLEAN_T); error_concealment.enable = MMAL_FALSE; status = mmal_port_parameter_set(m_dec_input, &error_concealment.hdr); if (status != MMAL_SUCCESS) CLog::Log(LOGERROR, "%s::%s Failed to disable error concealment on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); status = mmal_port_parameter_set_uint32(m_dec_input, MMAL_PARAMETER_EXTRA_BUFFERS, NUM_BUFFERS); if (status != MMAL_SUCCESS) CLog::Log(LOGERROR, "%s::%s Failed to enable extra buffers on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); status = mmal_port_format_commit(m_dec_input); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to commit format for decoder input port %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); return false; } m_dec_input->buffer_size = m_dec_input->buffer_size_recommended; m_dec_input->buffer_num = m_dec_input->buffer_num_recommended; m_dec_input->userdata = (struct MMAL_PORT_USERDATA_T *)this; status = mmal_port_enable(m_dec_input, dec_input_port_cb); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to enable decoder input port %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); return false; } m_dec_output = m_dec->output[0]; // set up initial decoded frame format - will likely change from this m_dec_output->format->encoding = MMAL_ENCODING_OPAQUE; mmal_format_copy(m_es_format, m_dec_output->format); status = mmal_port_format_commit(m_dec_output); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to commit decoder output format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } m_dec_output->buffer_size = m_dec_output->buffer_size_min; m_dec_output->buffer_num = m_dec_output->buffer_num_recommended; m_dec_output->userdata = (struct MMAL_PORT_USERDATA_T *)this; status = mmal_port_enable(m_dec_output, dec_output_port_cb_static); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to enable decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } status = mmal_component_enable(m_dec); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to enable decoder component %s (status=%x %s)", CLASSNAME, __func__, m_dec->name, status, mmal_status_to_string(status)); return false; } m_dec_input_pool = mmal_pool_create(m_dec_input->buffer_num, m_dec_input->buffer_size); if (!m_dec_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; } m_dec_output_pool = mmal_pool_create(m_dec_output->buffer_num, m_dec_output->buffer_size); if(!m_dec_output_pool) { CLog::Log(LOGERROR, "%s::%s Failed to create pool for decode output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } if (!SendCodecConfigData()) return false; m_drop_state = false; m_startframe = false; return true; }
static picture_pool_t *vd_pool(vout_display_t *vd, unsigned count) { vout_display_sys_t *sys = vd->sys; picture_resource_t picture_res; picture_pool_configuration_t picture_pool_cfg; video_format_t fmt = vd->fmt; MMAL_STATUS_T status; unsigned i; if (sys->picture_pool) { if (sys->num_buffers < count) msg_Warn(vd, "Picture pool with %u pictures requested, but we already have one with %u pictures", count, sys->num_buffers); goto out; } if (sys->opaque) { if (count <= NUM_ACTUAL_OPAQUE_BUFFERS) count = NUM_ACTUAL_OPAQUE_BUFFERS; } if (count < sys->input->buffer_num_recommended) count = sys->input->buffer_num_recommended; #ifndef NDEBUG msg_Dbg(vd, "Creating picture pool with %u pictures", count); #endif sys->input->buffer_num = count; status = mmal_port_enable(sys->input, input_port_cb); if (status != MMAL_SUCCESS) { msg_Err(vd, "Failed to enable input port %s (status=%"PRIx32" %s)", sys->input->name, status, mmal_status_to_string(status)); goto out; } status = mmal_component_enable(sys->component); if (status != MMAL_SUCCESS) { msg_Err(vd, "Failed to enable component %s (status=%"PRIx32" %s)", sys->component->name, status, mmal_status_to_string(status)); goto out; } sys->num_buffers = count; sys->pool = mmal_pool_create(sys->num_buffers, sys->input->buffer_size); if (!sys->pool) { msg_Err(vd, "Failed to create MMAL pool for %u buffers of size %"PRIu32, count, sys->input->buffer_size); goto out; } memset(&picture_res, 0, sizeof(picture_resource_t)); sys->pictures = calloc(sys->num_buffers, sizeof(picture_t *)); for (i = 0; i < sys->num_buffers; ++i) { picture_res.p_sys = calloc(1, sizeof(picture_sys_t)); picture_res.p_sys->owner = (vlc_object_t *)vd; picture_res.p_sys->queue = sys->pool->queue; sys->pictures[i] = picture_NewFromResource(&fmt, &picture_res); if (!sys->pictures[i]) { msg_Err(vd, "Failed to create picture"); free(picture_res.p_sys); goto out; } sys->pictures[i]->i_planes = sys->i_planes; memcpy(sys->pictures[i]->p, sys->planes, sys->i_planes * sizeof(plane_t)); } memset(&picture_pool_cfg, 0, sizeof(picture_pool_configuration_t)); picture_pool_cfg.picture_count = sys->num_buffers; picture_pool_cfg.picture = sys->pictures; picture_pool_cfg.lock = mmal_picture_lock; picture_pool_cfg.unlock = mmal_picture_unlock; sys->picture_pool = picture_pool_NewExtended(&picture_pool_cfg); if (!sys->picture_pool) { msg_Err(vd, "Failed to create picture pool"); goto out; } out: return sys->picture_pool; }