static void ffmmal_stop_decoder(AVCodecContext *avctx) { MMALDecodeContext *ctx = avctx->priv_data; MMAL_COMPONENT_T *decoder = ctx->decoder; MMAL_BUFFER_HEADER_T *buffer; mmal_port_disable(decoder->input[0]); mmal_port_disable(decoder->output[0]); mmal_port_disable(decoder->control); mmal_port_flush(decoder->input[0]); mmal_port_flush(decoder->output[0]); mmal_port_flush(decoder->control); while ((buffer = mmal_queue_get(ctx->queue_decoded_frames))) mmal_buffer_header_release(buffer); while (ctx->waiting_buffers) { FFBufferEntry *buffer = ctx->waiting_buffers; ctx->waiting_buffers = buffer->next; if (buffer->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END) avpriv_atomic_int_add_and_fetch(&ctx->packets_buffered, -1); av_buffer_unref(&buffer->ref); av_free(buffer); } ctx->waiting_buffers_tail = NULL; av_assert0(avpriv_atomic_int_get(&ctx->packets_buffered) == 0); ctx->frames_output = ctx->eos_received = ctx->eos_sent = ctx->packets_sent = ctx->extradata_sent = 0; }
static void ffmmal_stop_decoder(AVCodecContext *avctx) { MMALDecodeContext *ctx = avctx->priv_data; MMAL_COMPONENT_T *decoder = ctx->decoder; MMAL_BUFFER_HEADER_T *buffer; mmal_port_disable(decoder->input[0]); mmal_port_disable(decoder->output[0]); mmal_port_disable(decoder->control); mmal_port_flush(decoder->input[0]); mmal_port_flush(decoder->output[0]); mmal_port_flush(decoder->control); while ((buffer = mmal_queue_get(ctx->queue_decoded_frames))) mmal_buffer_header_release(buffer); while (ctx->waiting_buffers) { FFBufferEntry *buffer = ctx->waiting_buffers; ctx->waiting_buffers = buffer->next; av_buffer_unref(&buffer->ref); av_free(buffer); } ctx->waiting_buffers_tail = NULL; ctx->frames_output = ctx->eos_received = ctx->eos_sent = ctx->packets_sent = 0; }
static void flush(filter_t *filter) { filter_sys_t *sys = filter->p_sys; MMAL_BUFFER_HEADER_T *buffer; msg_Dbg(filter, "flush deinterlace filter"); if (atomic_load(&sys->input_in_transit) || atomic_load(&sys->output_in_transit)) { msg_Dbg(filter, "flush: flush ports (input: %d, output: %d in transit)", sys->input_in_transit, sys->output_in_transit); mmal_port_flush(sys->output); mmal_port_flush(sys->input); msg_Dbg(filter, "flush: wait for all buffers to be returned"); vlc_mutex_lock(&sys->buffer_cond_mutex); while (atomic_load(&sys->input_in_transit) || atomic_load(&sys->output_in_transit)) { vlc_cond_wait(&sys->buffer_cond, &sys->buffer_cond_mutex); } vlc_mutex_unlock(&sys->buffer_cond_mutex); } while ((buffer = mmal_queue_get(sys->filtered_pictures))) { picture_t *pic = (picture_t *)buffer->user_data; msg_Dbg(filter, "flush: release already filtered pic %p", (void *)pic); picture_Release(pic); } msg_Dbg(filter, "flush: done"); }
static int flush_decoder(decoder_t *dec) { decoder_sys_t *sys = dec->p_sys; MMAL_BUFFER_HEADER_T *buffer; MMAL_STATUS_T status; int ret = 0; msg_Dbg(dec, "Flushing decoder ports..."); mmal_port_disable(sys->output); mmal_port_disable(sys->input); mmal_port_flush(sys->output); mmal_port_flush(sys->input); /* Reload extradata if available */ 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)); } mmal_port_enable(sys->output, output_port_cb); mmal_port_enable(sys->input, input_port_cb); while (atomic_load(&sys->output_in_transit)) vlc_sem_wait(&sys->sem); /* Free pictures which are decoded but have not yet been sent * out to the core */ while ((buffer = mmal_queue_get(sys->decoded_pictures))) { picture_t *pic = (picture_t *)buffer->user_data; picture_Release(pic); if (sys->output_pool) { buffer->user_data = NULL; buffer->alloc_size = 0; buffer->data = NULL; mmal_buffer_header_release(buffer); } } msg_Dbg(dec, "Ports flushed, returning to normal operation"); return ret; }
static void disable_renderer(struct gl_hwdec *hw) { struct priv *p = hw->priv; if (p->renderer_enabled) { mmal_port_disable(p->renderer->control); mmal_port_disable(p->renderer->input[0]); mmal_port_flush(p->renderer->control); mmal_port_flush(p->renderer->input[0]); mmal_component_disable(p->renderer); } mmal_pool_destroy(p->swpool); p->swpool = NULL; p->renderer_enabled = false; }
void CMMALRenderer::UnInitMMAL() { CSingleLock lock(m_sharedSection); CLog::Log(LOGDEBUG, "%s::%s pool(%p)", CLASSNAME, __func__, m_vout_input_pool); if (m_queue) { StopThread(true); mmal_queue_destroy(m_queue); m_queue = nullptr; } if (m_vout) { mmal_component_disable(m_vout); } if (m_vout_input) { mmal_port_flush(m_vout_input); mmal_port_disable(m_vout_input); } ReleaseBuffers(); if (m_vout_input_pool) { mmal_port_pool_destroy(m_vout_input, m_vout_input_pool); m_vout_input_pool = NULL; } m_vout_input = NULL; if (m_vout) { mmal_component_release(m_vout); m_vout = NULL; } m_src_rect.SetRect(0, 0, 0, 0); m_dst_rect.SetRect(0, 0, 0, 0); m_video_stereo_mode = RENDER_STEREO_MODE_OFF; m_display_stereo_mode = RENDER_STEREO_MODE_OFF; m_StereoInvert = false; m_format = RENDER_FMT_NONE; m_bConfigured = false; m_bMMALConfigured = false; }
static BRCMIMAGE_STATUS_T brcmimage_decode(BRCMIMAGE_T *ctx, BRCMIMAGE_REQUEST_T *jd) { BRCMIMAGE_STATUS_T err; MMAL_STATUS_T status; MMAL_BUFFER_HEADER_T *in, *out; MMAL_BOOL_T eos = MMAL_FALSE; const uint8_t *inBuf = jd->input; unsigned int slices = 0, inBufSize = jd->input_size; MMAL_PORT_T *port_in = ctx->mmal->input[0]; MMAL_PORT_T *port_out = ctx->mmal->output[0]; LOG_DEBUG("decode %i bytes\n", jd->input_size); jd->output_size = 0; err = brcmimage_configure_decoder(ctx, jd); if (err != BRCMIMAGE_SUCCESS) return err; while (!eos) { /* Send as many chunks of data to decode as we can */ while (inBufSize) { status = mmal_wrapper_buffer_get_empty(port_in, &in, 0); if (status == MMAL_EAGAIN) break; CHECK_MMAL_STATUS(status, EXECUTE, "failed to get empty buffer (%i)", status); in->data = (uint8_t *)inBuf; in->length = MMAL_MIN(port_in->buffer_size, inBufSize); in->alloc_size = in->length; inBufSize -= in->length; inBuf += in->length; in->flags = inBufSize ? 0 : MMAL_BUFFER_HEADER_FLAG_EOS; LOG_DEBUG("send decode in (%i bytes)\n", in->length); status = mmal_port_send_buffer(port_in, in); CHECK_MMAL_STATUS(status, EXECUTE, "failed to send input buffer"); } /* Check for decoded data */ status = mmal_wrapper_buffer_get_full(port_out, &out, 0); if (status == MMAL_EAGAIN) { WAIT(ctx); continue; } CHECK_MMAL_STATUS(status, EXECUTE, "error decoding"); /* Check if a new format has been auto-detected by the decoder */ if (out->cmd == MMAL_EVENT_FORMAT_CHANGED) { MMAL_EVENT_FORMAT_CHANGED_T *event = mmal_event_format_changed_get(out); if (event) mmal_format_copy(port_out->format, event->format); mmal_buffer_header_release(out); if (!event) status = MMAL_EINVAL; CHECK_MMAL_STATUS(status, EXECUTE, "invalid format change event"); LOG_DEBUG("new format (%4.4s:%ux%u|%ux%u)\n", (char *)&event->format->encoding, event->format->es->video.crop.width, event->format->es->video.crop.height, event->format->es->video.width, event->format->es->video.height); /* re-setup the output port for the new format */ status = mmal_wrapper_port_disable(port_out); CHECK_MMAL_STATUS(status, EXECUTE, "failed to disable output port"); ctx->slice_height = event->format->es->video.height; if (ENABLE_SLICE_MODE && !jd->output_handle) { /* setup slice mode */ if (port_out->format->encoding == MMAL_ENCODING_I420 || port_out->format->encoding == MMAL_ENCODING_I422) { if (port_out->format->encoding == MMAL_ENCODING_I420) port_out->format->encoding = MMAL_ENCODING_I420_SLICE; if (port_out->format->encoding == MMAL_ENCODING_I422) port_out->format->encoding = MMAL_ENCODING_I422_SLICE; ctx->slice_height = 16; port_out->buffer_num = 3; } } LOG_DEBUG("using slice size %u\n", ctx->slice_height); status = mmal_port_format_commit(port_out); CHECK_MMAL_STATUS(status, EXECUTE, "invalid format change event"); port_out->buffer_size = port_out->buffer_size_min; if (jd->output_handle) status = mmal_wrapper_port_enable(port_out, MMAL_WRAPPER_FLAG_PAYLOAD_USE_SHARED_MEMORY); else status = mmal_wrapper_port_enable(port_out, MMAL_WRAPPER_FLAG_PAYLOAD_ALLOCATE); CHECK_MMAL_STATUS(status, EXECUTE, "failed to enable output port"); /* send all our output buffers to the decoder */ while (mmal_wrapper_buffer_get_empty(port_out, &out, 0) == MMAL_SUCCESS) { if (jd->output_handle) { out->data = (uint8_t*)jd->output_handle; out->alloc_size = jd->output_alloc_size; } status = mmal_port_send_buffer(port_out, out); CHECK_MMAL_STATUS(status, EXECUTE, "failed to send output buffer"); } continue; } /* We have part of our output frame */ jd->width = port_out->format->es->video.crop.width; if (!jd->width) jd->width = port_out->format->es->video.width; if (jd->output_handle) jd->buffer_width = port_out->format->es->video.width; if (!jd->buffer_width) jd->buffer_width = jd->width; jd->height = port_out->format->es->video.crop.height; if (!jd->height) jd->height = port_out->format->es->video.height; if (jd->output_handle) jd->buffer_height = port_out->format->es->video.height; if (!jd->buffer_height) jd->buffer_height = jd->height; if (jd->output_handle) { jd->output_size += out->length; } else { jd->output_size = brcmimage_copy_pixels(jd->output, jd->output_alloc_size, out->data, out->length, jd->pixel_format, jd->buffer_width, jd->buffer_height, port_out->format->es->video.width, ctx->slice_height, slices * ctx->slice_height, 0); slices++; } eos = out->flags & MMAL_BUFFER_HEADER_FLAG_EOS; out->length = 0; if (eos) { mmal_buffer_header_release(out); } else { status = mmal_port_send_buffer(port_out, out); CHECK_MMAL_STATUS(status, EXECUTE, "failed to send output buffer"); } if (!jd->output_size) status = MMAL_EINVAL; CHECK_MMAL_STATUS(status, OUTPUT_BUFFER, "invalid output buffer"); } LOG_DEBUG("decoded W:%ixH%i:(W%ixH%i):%i in %i slices\n", jd->width, jd->height, jd->buffer_width, jd->buffer_height, jd->pixel_format, slices); mmal_port_flush(port_in); return BRCMIMAGE_SUCCESS; error: mmal_port_flush(port_in); return err; }
static BRCMIMAGE_STATUS_T brcmimage_encode(BRCMIMAGE_T *ctx, BRCMIMAGE_REQUEST_T *je) { BRCMIMAGE_STATUS_T err; MMAL_STATUS_T status = MMAL_SUCCESS; MMAL_BUFFER_HEADER_T *in, *out; MMAL_BOOL_T eos = MMAL_FALSE; const uint8_t *outBuf = je->output; unsigned int loop = 0, slices = 0, outBufSize = je->output_alloc_size; MMAL_PORT_T *port_in = ctx->mmal->input[0]; MMAL_PORT_T *port_out = ctx->mmal->output[0]; je->output_size = 0; err = brcmimage_configure_encoder(ctx, je); if (err != BRCMIMAGE_SUCCESS) return err; /* Then we read the encoded data back from the encoder */ while (!eos && status == MMAL_SUCCESS) { /* send buffers to be filled */ while (mmal_wrapper_buffer_get_empty(port_out, &out, 0) == MMAL_SUCCESS) { out->data = (uint8_t *)outBuf; out->alloc_size = MMAL_MIN(port_out->buffer_size, outBufSize); outBufSize -= out->alloc_size; outBuf += out->alloc_size; status = mmal_port_send_buffer(port_out, out); CHECK_MMAL_STATUS(status, EXECUTE, "failed to send buffer"); } /* Send slices to be encoded */ if (slices * ctx->slice_height < port_in->format->es->video.height && mmal_wrapper_buffer_get_empty(port_in, &in, 0) == MMAL_SUCCESS) { if (je->input_handle) { in->data = (uint8_t *)je->input_handle; in->length = in->alloc_size = je->input_size; } else { in->length = brcmimage_copy_pixels(in->data, in->alloc_size, je->input, je->input_size, je->pixel_format, port_in->format->es->video.width, ctx->slice_height, je->buffer_width, je->buffer_height, slices * ctx->slice_height, 1); if (!in->length) status = MMAL_EINVAL; CHECK_MMAL_STATUS(status, INPUT_BUFFER, "input buffer too small"); } slices++; if (slices * ctx->slice_height >= port_in->format->es->video.height) in->flags = MMAL_BUFFER_HEADER_FLAG_EOS; status = mmal_port_send_buffer(port_in, in); CHECK_MMAL_STATUS(status, EXECUTE, "failed to send buffer"); } status = mmal_wrapper_buffer_get_full(port_out, &out, 0); if (status == MMAL_EAGAIN) { status = MMAL_SUCCESS; WAIT(ctx); continue; } CHECK_MMAL_STATUS(status, EXECUTE, "failed to get full buffer"); LOG_DEBUG("received %i bytes\n", out->length); je->output_size += out->length; eos = out->flags & MMAL_BUFFER_HEADER_FLAG_EOS; /* Detect when the encoder is running out of space for its output */ if (++loop >= port_out->buffer_num && !eos && !out->length) { LOG_ERROR("no more output space for encoder"); status = MMAL_EINVAL; } mmal_buffer_header_release(out); } /* Check if buffer was too small */ CHECK_MMAL_STATUS(status, OUTPUT_BUFFER, "output buffer too small"); LOG_DEBUG("encoded W:%ixH:%i:%i (%i bytes) in %i slices\n", je->width, je->height, je->pixel_format, je->output_size, slices); mmal_port_flush(port_out); return BRCMIMAGE_SUCCESS; error: mmal_wrapper_port_disable(port_in); mmal_wrapper_port_disable(port_out); return err; }