static void vlVdpDecoderFixVC1Startcode(uint32_t *num_buffers, const void *buffers[], unsigned sizes[]) { static const uint8_t vc1_startcode[] = { 0x00, 0x00, 0x01, 0x0D }; struct vl_vlc vlc; unsigned i; /* search the first 64 bytes for a startcode */ vl_vlc_init(&vlc, *num_buffers, buffers, sizes); while (vl_vlc_search_byte(&vlc, 64*8, 0x00) && vl_vlc_bits_left(&vlc) >= 32) { uint32_t value = vl_vlc_peekbits(&vlc, 32); if (value == 0x0000010D || value == 0x0000010C || value == 0x0000010B) return; vl_vlc_eatbits(&vlc, 8); } /* none found, ok add one manually */ VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Manually adding VC-1 startcode\n"); for (i = *num_buffers; i > 0; --i) { buffers[i] = buffers[i - 1]; sizes[i] = sizes[i - 1]; } ++(*num_buffers); buffers[0] = vc1_startcode; sizes[0] = 4; }
static unsigned int bufHasStartcode(vlVaBuffer *buf, unsigned int code, unsigned int bits) { struct vl_vlc vlc = {0}; int i; /* search the first 64 bytes for a startcode */ vl_vlc_init(&vlc, 1, (const void * const*)&buf->data, &buf->size); for (i = 0; i < 64 && vl_vlc_bits_left(&vlc) >= bits; ++i) { if (vl_vlc_peekbits(&vlc, bits) == code) return 1; vl_vlc_eatbits(&vlc, 8); vl_vlc_fillbits(&vlc); } return 0; }
static OMX_ERRORTYPE vid_dec_DecodeBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf) { OMX_COMPONENTTYPE* comp = port->standCompContainer; vid_dec_PrivateType *priv = comp->pComponentPrivate; unsigned i = priv->num_in_buffers++; OMX_ERRORTYPE r; priv->in_buffers[i] = buf; priv->sizes[i] = buf->nFilledLen; priv->inputs[i] = buf->pBuffer; priv->timestamps[i] = buf->nTimeStamp; while (priv->num_in_buffers > (!!(buf->nFlags & OMX_BUFFERFLAG_EOS) ? 0 : 1)) { bool eos = !!(priv->in_buffers[0]->nFlags & OMX_BUFFERFLAG_EOS); unsigned min_bits_left = eos ? 32 : MAX2(buf->nFilledLen * 8, 32); struct vl_vlc vlc; vl_vlc_init(&vlc, priv->num_in_buffers, priv->inputs, priv->sizes); if (priv->slice) priv->bytes_left = vl_vlc_bits_left(&vlc) / 8; while (vl_vlc_bits_left(&vlc) > min_bits_left) { priv->Decode(priv, &vlc, min_bits_left); vl_vlc_fillbits(&vlc); } if (priv->slice) { unsigned bytes = priv->bytes_left - vl_vlc_bits_left(&vlc) / 8; priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, 1, &priv->slice, &bytes); if (priv->num_in_buffers) priv->slice = priv->inputs[1]; else priv->slice = NULL; } if (eos && priv->frame_started) priv->EndFrame(priv); if (priv->frame_finished) { priv->frame_finished = false; priv->in_buffers[0]->nFilledLen = priv->in_buffers[0]->nAllocLen; r = base_port_SendBufferFunction(port, priv->in_buffers[0]); } else if (eos) { vid_dec_FreeInputPortPrivate(priv->in_buffers[0]); priv->in_buffers[0]->nFilledLen = priv->in_buffers[0]->nAllocLen; r = base_port_SendBufferFunction(port, priv->in_buffers[0]); } else { priv->in_buffers[0]->nFilledLen = 0; r = port->ReturnBufferFunction(port, priv->in_buffers[0]); } if (--priv->num_in_buffers) { unsigned delta = MIN2((min_bits_left - vl_vlc_bits_left(&vlc)) / 8, priv->sizes[1]); priv->in_buffers[0] = priv->in_buffers[1]; priv->sizes[0] = priv->sizes[1] - delta; priv->inputs[0] = priv->inputs[1] + delta; priv->timestamps[0] = priv->timestamps[1]; } if (r) return r; } return OMX_ErrorNone; }
static OMX_ERRORTYPE decode_frame(vid_dec_PrivateType*priv, OMX_BUFFERHEADERTYPE *in_buf) { unsigned i = priv->num_in_buffers++; priv->in_buffers[i] = in_buf; priv->sizes[i] = in_buf->nFilledLen; priv->inputs[i] = in_buf->pBuffer; priv->timestamps[i] = in_buf->nTimeStamp; while (priv->num_in_buffers > (!!(in_buf->nFlags & OMX_BUFFERFLAG_EOS) ? 0 : 1)) { priv->eos_ = !!(priv->in_buffers[0]->nFlags & OMX_BUFFERFLAG_EOS); unsigned min_bits_left = priv->eos_ ? 32 : MAX2(in_buf->nFilledLen * 8, 32); struct vl_vlc vlc; vl_vlc_init(&vlc, priv->num_in_buffers, priv->inputs, priv->sizes); if (priv->slice) priv->bytes_left = vl_vlc_bits_left(&vlc) / 8; while (vl_vlc_bits_left (&vlc) > min_bits_left) { vid_dec_h264_Decode(priv, &vlc, min_bits_left); vl_vlc_fillbits(&vlc); } if (priv->slice) { unsigned bytes = priv->bytes_left - vl_vlc_bits_left(&vlc) / 8; priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, 1, &priv->slice, &bytes); if (priv->num_in_buffers) priv->slice = priv->inputs[1]; else priv->slice = NULL; } if (priv->eos_ && priv->frame_started) vid_dec_h264_EndFrame(priv); if (priv->frame_finished) { priv->frame_finished = false; h264d_manage_buffers(priv); } else if (priv->eos_) { vid_dec_FreeInputPortPrivate(priv->in_buffers[0]); h264d_manage_buffers(priv); } else { priv->in_buffers[0]->nFilledLen = 0; h264d_buffer_emptied(priv, priv->in_buffers[0]); } if (priv->out_port_disabled_) { /* In case out port is disabled, h264d_buffer_emptied will fail to release input port. * We need to wait before shifting the buffers in that case and check in * get_input_buffer when out port is enabled to release and shift the buffers. * Infinite looping occurs if buffer is not released */ if (priv->num_in_buffers == 2) { /* Set the delta value for use in get_input_buffer before exiting */ dec_frame_delta = MIN2((min_bits_left - vl_vlc_bits_left(&vlc)) / 8, priv->sizes[1]); } break; } h264d_shift_buffers_left(priv); } return OMX_ErrorNone; }