diff options
Diffstat (limited to 'src/gallium/state_trackers/omx/bellagio/vid_dec_mpeg12.c')
-rw-r--r-- | src/gallium/state_trackers/omx/bellagio/vid_dec_mpeg12.c | 383 |
1 files changed, 383 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/omx/bellagio/vid_dec_mpeg12.c b/src/gallium/state_trackers/omx/bellagio/vid_dec_mpeg12.c new file mode 100644 index 00000000000..f64c2b83fa5 --- /dev/null +++ b/src/gallium/state_trackers/omx/bellagio/vid_dec_mpeg12.c @@ -0,0 +1,383 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * Authors: + * Christian König <[email protected]> + * + */ + +#include "pipe/p_video_codec.h" +#include "vl/vl_vlc.h" +#include "vl/vl_zscan.h" + +#include "vid_dec.h" + +static uint8_t default_intra_matrix[64] = { + 8, 16, 19, 22, 26, 27, 29, 34, + 16, 16, 22, 24, 27, 29, 34, 37, + 19, 22, 26, 27, 29, 34, 34, 38, + 22, 22, 26, 27, 29, 34, 37, 40, + 22, 26, 27, 29, 32, 35, 40, 48, + 26, 27, 29, 32, 35, 40, 48, 58, + 26, 27, 29, 34, 38, 46, 56, 69, + 27, 29, 35, 38, 46, 56, 69, 83 +}; + +static uint8_t default_non_intra_matrix[64] = { + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16 +}; + +static void vid_dec_mpeg12_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left); +static void vid_dec_mpeg12_EndFrame(vid_dec_PrivateType *priv); +static struct pipe_video_buffer *vid_dec_mpeg12_Flush(vid_dec_PrivateType *priv, OMX_TICKS *timestamp); + +void vid_dec_mpeg12_Init(vid_dec_PrivateType *priv) +{ + struct pipe_video_codec templat = {}; + omx_base_video_PortType *port; + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; + templat.profile = priv->profile; + templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; + templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + templat.max_references = 2; + templat.expect_chunked_decode = true; + templat.width = port->sPortParam.format.video.nFrameWidth; + templat.height = port->sPortParam.format.video.nFrameHeight; + + priv->codec = priv->pipe->create_video_codec(priv->pipe, &templat); + + priv->picture.base.profile = PIPE_VIDEO_PROFILE_MPEG2_MAIN; + priv->picture.mpeg12.intra_matrix = default_intra_matrix; + priv->picture.mpeg12.non_intra_matrix = default_non_intra_matrix; + + priv->Decode = vid_dec_mpeg12_Decode; + priv->EndFrame = vid_dec_mpeg12_EndFrame; + priv->Flush = vid_dec_mpeg12_Flush; +} + +static void BeginFrame(vid_dec_PrivateType *priv) +{ + if (priv->picture.mpeg12.picture_coding_type != PIPE_MPEG12_PICTURE_CODING_TYPE_B) { + priv->picture.mpeg12.ref[0] = priv->picture.mpeg12.ref[1]; + priv->picture.mpeg12.ref[1] = NULL; + } + + if (priv->target == priv->picture.mpeg12.ref[0]) { + struct pipe_video_buffer *tmp = priv->target; + priv->target = priv->shadow; + priv->shadow = tmp; + } + + vid_dec_NeedTarget(priv); + + priv->codec->begin_frame(priv->codec, priv->target, &priv->picture.base); + priv->frame_started = true; +} + +static void vid_dec_mpeg12_EndFrame(vid_dec_PrivateType *priv) +{ + struct pipe_video_buffer *done; + + priv->codec->end_frame(priv->codec, priv->target, &priv->picture.base); + priv->frame_started = false; + + if (priv->picture.mpeg12.picture_coding_type != PIPE_MPEG12_PICTURE_CODING_TYPE_B) { + + priv->picture.mpeg12.ref[1] = priv->target; + done = priv->picture.mpeg12.ref[0]; + if (!done) { + priv->target = NULL; + return; + } + + } else + done = priv->target; + + priv->frame_finished = true; + priv->target = priv->in_buffers[0]->pInputPortPrivate; + priv->in_buffers[0]->pInputPortPrivate = done; +} + +static struct pipe_video_buffer *vid_dec_mpeg12_Flush(vid_dec_PrivateType *priv, OMX_TICKS *timestamp) +{ + struct pipe_video_buffer *result = priv->picture.mpeg12.ref[1]; + priv->picture.mpeg12.ref[1] = NULL; + if (timestamp) + *timestamp = OMX_VID_DEC_TIMESTAMP_INVALID; + return result; +} + +static void vid_dec_mpeg12_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left) +{ + uint8_t code; + unsigned i; + + if (!vl_vlc_search_byte(vlc, vl_vlc_bits_left(vlc) - min_bits_left, 0x00)) + return; + + if (vl_vlc_peekbits(vlc, 24) != 0x000001) { + vl_vlc_eatbits(vlc, 8); + return; + } + + 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); + priv->slice = NULL; + } + + vl_vlc_eatbits(vlc, 24); + code = vl_vlc_get_uimsbf(vlc, 8); + + if (priv->frame_started && (code == 0x00 || code > 0xAF)) + vid_dec_mpeg12_EndFrame(priv); + + if (code == 0xB3) { + /* sequence header code */ + vl_vlc_fillbits(vlc); + + /* horizontal_size_value */ + vl_vlc_get_uimsbf(vlc, 12); + + /* vertical_size_value */ + vl_vlc_get_uimsbf(vlc, 12); + + /* aspect_ratio_information */ + vl_vlc_get_uimsbf(vlc, 4); + + /* frame_rate_code */ + vl_vlc_get_uimsbf(vlc, 4); + + vl_vlc_fillbits(vlc); + + /* bit_rate_value */ + vl_vlc_get_uimsbf(vlc, 18); + + /* marker_bit */ + vl_vlc_get_uimsbf(vlc, 1); + + /* vbv_buffer_size_value */ + vl_vlc_get_uimsbf(vlc, 10); + + /* constrained_parameters_flag */ + vl_vlc_get_uimsbf(vlc, 1); + + vl_vlc_fillbits(vlc); + + /* load_intra_quantiser_matrix */ + if (vl_vlc_get_uimsbf(vlc, 1)) { + /* intra_quantiser_matrix */ + priv->picture.mpeg12.intra_matrix = priv->codec_data.mpeg12.intra_matrix; + for (i = 0; i < 64; ++i) { + priv->codec_data.mpeg12.intra_matrix[vl_zscan_normal[i]] = vl_vlc_get_uimsbf(vlc, 8); + vl_vlc_fillbits(vlc); + } + } else + priv->picture.mpeg12.intra_matrix = default_intra_matrix; + + /* load_non_intra_quantiser_matrix */ + if (vl_vlc_get_uimsbf(vlc, 1)) { + /* non_intra_quantiser_matrix */ + priv->picture.mpeg12.non_intra_matrix = priv->codec_data.mpeg12.non_intra_matrix; + for (i = 0; i < 64; ++i) { + priv->codec_data.mpeg12.non_intra_matrix[i] = vl_vlc_get_uimsbf(vlc, 8); + vl_vlc_fillbits(vlc); + } + } else + priv->picture.mpeg12.non_intra_matrix = default_non_intra_matrix; + + } else if (code == 0x00) { + /* picture start code */ + vl_vlc_fillbits(vlc); + + /* temporal_reference */ + vl_vlc_get_uimsbf(vlc, 10); + + priv->picture.mpeg12.picture_coding_type = vl_vlc_get_uimsbf(vlc, 3); + + /* vbv_delay */ + vl_vlc_get_uimsbf(vlc, 16); + + vl_vlc_fillbits(vlc); + if (priv->picture.mpeg12.picture_coding_type == 2 || + priv->picture.mpeg12.picture_coding_type == 3) { + priv->picture.mpeg12.full_pel_forward_vector = vl_vlc_get_uimsbf(vlc, 1); + /* forward_f_code */ + priv->picture.mpeg12.f_code[0][0] = vl_vlc_get_uimsbf(vlc, 3) - 1; + priv->picture.mpeg12.f_code[0][1] = priv->picture.mpeg12.f_code[0][0]; + } else { + priv->picture.mpeg12.full_pel_forward_vector = 0; + priv->picture.mpeg12.f_code[0][1] = priv->picture.mpeg12.f_code[0][0] = 14; + } + + if (priv->picture.mpeg12.picture_coding_type == 3) { + priv->picture.mpeg12.full_pel_backward_vector = vl_vlc_get_uimsbf(vlc, 1); + /* backward_f_code */ + priv->picture.mpeg12.f_code[1][0] = vl_vlc_get_uimsbf(vlc, 3) - 1; + priv->picture.mpeg12.f_code[1][1] = priv->picture.mpeg12.f_code[1][0]; + } else { + priv->picture.mpeg12.full_pel_backward_vector = 0; + priv->picture.mpeg12.f_code[0][1] = priv->picture.mpeg12.f_code[0][0] = 14; + } + + /* extra_bit_picture */ + while (vl_vlc_get_uimsbf(vlc, 1)) { + /* extra_information_picture */ + vl_vlc_get_uimsbf(vlc, 8); + vl_vlc_fillbits(vlc); + } + + } else if (code == 0xB5) { + /* extension start code */ + vl_vlc_fillbits(vlc); + + /* extension_start_code_identifier */ + switch (vl_vlc_get_uimsbf(vlc, 4)) { + case 0x3: /* quant matrix extension */ + + /* load_intra_quantiser_matrix */ + if (vl_vlc_get_uimsbf(vlc, 1)) { + /* intra_quantiser_matrix */ + priv->picture.mpeg12.intra_matrix = priv->codec_data.mpeg12.intra_matrix; + for (i = 0; i < 64; ++i) { + priv->codec_data.mpeg12.intra_matrix[vl_zscan_normal[i]] = vl_vlc_get_uimsbf(vlc, 8); + vl_vlc_fillbits(vlc); + } + } else + priv->picture.mpeg12.intra_matrix = default_intra_matrix; + + /* load_non_intra_quantiser_matrix */ + if (vl_vlc_get_uimsbf(vlc, 1)) { + /* non_intra_quantiser_matrix */ + priv->picture.mpeg12.non_intra_matrix = priv->codec_data.mpeg12.non_intra_matrix; + for (i = 0; i < 64; ++i) { + priv->codec_data.mpeg12.non_intra_matrix[i] = vl_vlc_get_uimsbf(vlc, 8); + vl_vlc_fillbits(vlc); + } + } else + priv->picture.mpeg12.intra_matrix = default_non_intra_matrix; + + break; + + case 0x8: /* picture coding extension */ + + priv->picture.mpeg12.f_code[0][0] = vl_vlc_get_uimsbf(vlc, 4) - 1; + priv->picture.mpeg12.f_code[0][1] = vl_vlc_get_uimsbf(vlc, 4) - 1; + priv->picture.mpeg12.f_code[1][0] = vl_vlc_get_uimsbf(vlc, 4) - 1; + priv->picture.mpeg12.f_code[1][1] = vl_vlc_get_uimsbf(vlc, 4) - 1; + priv->picture.mpeg12.intra_dc_precision = vl_vlc_get_uimsbf(vlc, 2); + priv->picture.mpeg12.picture_structure = vl_vlc_get_uimsbf(vlc, 2); + priv->picture.mpeg12.top_field_first = vl_vlc_get_uimsbf(vlc, 1); + priv->picture.mpeg12.frame_pred_frame_dct = vl_vlc_get_uimsbf(vlc, 1); + priv->picture.mpeg12.concealment_motion_vectors = vl_vlc_get_uimsbf(vlc, 1); + priv->picture.mpeg12.q_scale_type = vl_vlc_get_uimsbf(vlc, 1); + priv->picture.mpeg12.intra_vlc_format = vl_vlc_get_uimsbf(vlc, 1); + priv->picture.mpeg12.alternate_scan = vl_vlc_get_uimsbf(vlc, 1); + + /* repeat_first_field */ + vl_vlc_get_uimsbf(vlc, 1); + + /* chroma_420_type */ + vl_vlc_get_uimsbf(vlc, 1); + + vl_vlc_fillbits(vlc); + + /* progressive_frame */ + vl_vlc_get_uimsbf(vlc, 1); + + /* composite_display_flag */ + if (vl_vlc_get_uimsbf(vlc, 1)) { + + /* v_axis */ + vl_vlc_get_uimsbf(vlc, 1); + + /* field_sequence */ + vl_vlc_get_uimsbf(vlc, 3); + + /* sub_carrier */ + vl_vlc_get_uimsbf(vlc, 1); + + /* burst_amplitude */ + vl_vlc_get_uimsbf(vlc, 7); + + /* sub_carrier_phase */ + vl_vlc_get_uimsbf(vlc, 8); + } + break; + } + + } else if (code <= 0xAF) { + /* slice start */ + unsigned bytes = (vl_vlc_valid_bits(vlc) / 8) + 4; + uint8_t buf[12]; + const void *ptr = buf; + unsigned i; + + if (!priv->frame_started) + BeginFrame(priv); + + buf[0] = 0x00; + buf[1] = 0x00; + buf[2] = 0x01; + buf[3] = code; + for (i = 4; i < bytes; ++i) + buf[i] = vl_vlc_get_uimsbf(vlc, 8); + + priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, + 1, &ptr, &bytes); + + priv->bytes_left = vl_vlc_bits_left(vlc) / 8; + priv->slice = vlc->data; + + } else if (code == 0xB2) { + /* user data start */ + + } else if (code == 0xB4) { + /* sequence error */ + } else if (code == 0xB7) { + /* sequence end */ + } else if (code == 0xB8) { + /* group start */ + } else if (code >= 0xB9) { + /* system start */ + } else { + /* reserved */ + } + + /* resync to byte boundary */ + vl_vlc_eatbits(vlc, vl_vlc_valid_bits(vlc) % 8); +} |