Ejemplo n.º 1
0
/*!
 * \param *dc The current DecodingContext.
 * \param mbAddr The current macroblock address.
 * \return 0 if macroblock decoding fail, 1 otherwise.
 *
 * This function extract one macroblock from the bitstream, handle intra/inter
 * prediction for its blocks.
 */
int macroblock_layer(DecodingContext_t *dc, const int mbAddr)
{
    TRACE_INFO(MB, "<> " BLD_GREEN "macroblock_layer(" CLR_RESET "%i" BLD_GREEN ")\n" CLR_RESET, mbAddr);
    int retcode = FAILURE;

    // Macroblock allocation
    ////////////////////////////////////////////////////////////////////////////

    dc->mb_array[mbAddr] = (Macroblock_t*)calloc(1, sizeof(Macroblock_t));

    if (dc->mb_array[mbAddr] == NULL)
    {
        TRACE_ERROR(MB, "Unable to alloc new macroblock!\n");
    }
    else
    {
        // Set macroblock address
        dc->mb_array[mbAddr]->mbAddr = mbAddr;

        // Shortcuts
        pps_t *pps = dc->pps_array[dc->active_slice->pic_parameter_set_id];
        sps_t *sps = dc->sps_array[pps->seq_parameter_set_id];
        slice_t *slice = dc->active_slice;
        Macroblock_t *mb = dc->mb_array[mbAddr];

        // Macroblock decoding
        ////////////////////////////////////////////////////////////////////////

#if ENABLE_DEBUG
        mb->mbFileAddrStart = bitstream_get_absolute_bit_offset(dc->bitstr);
#endif // ENABLE_DEBUG

        deriv_macroblockneighbours_availability(dc, mbAddr);
        MbPosition(mb, sps);

        if (pps->entropy_coding_mode_flag)
            mb->mb_type = read_ae(dc, SE_mb_type);
        else
            mb->mb_type = read_ue(dc->bitstr);

        mb->MbPartPredMode[0] = MbPartPredMode(mb, slice->slice_type, 0);
        mb->NumMbPart = NumMbPart(slice->slice_type, mb->mb_type);

        if (mb->mb_type == I_PCM)
        {
#if ENABLE_IPCM
            TRACE_3(MB, "---- macroblock_layer - I PCM macroblock\n");

            while (bitstream_check_alignment(dc->bitstr) == false)
            {
                if (read_bit(dc->bitstr) != 0) // pcm_alignment_zero_bit
                {
                    TRACE_ERROR(MB, "  Error while reading pcm_alignment_zero_bit: must be 0!\n");
                    return FAILURE;
                }
            }

            // CABAC initialization process //FIXME needed? See 'ITU-T H.264' recommendation 9.3.1.2
            initCabacDecodingEngine(dc);

            int i = 0;
            for (i = 0; i < 256; i++)
            {
                mb->pcm_sample_luma[i] = (uint8_t)read_bits(dc->bitstr, sps->BitDepthY);
            }

            // CABAC initialization process //FIXME needed? See 'ITU-T H.264' recommendation 9.3.1.2
            initCabacDecodingEngine(dc);

            for (i = 0; i < 2 * sps->MbWidthC * sps->MbHeightC; i++)
            {
                mb->pcm_sample_chroma[i] = (uint8_t)read_bits(dc->bitstr, sps->BitDepthC);
            }

            // CABAC initialization process //FIXME needed? See 'ITU-T H.264' recommendation 9.3.1.2
            initCabacDecodingEngine(dc);
#else // ENABLE_IPCM
            TRACE_ERROR(MB, "I_PCM decoding is currently disabled!\n");
            return UNSUPPORTED;
#endif // ENABLE_IPCM
        }
        else
        {
#if ENABLE_INTER_PRED
            bool noSubMbPartSizeLessThan8x8Flag = true;

            if (mb->mb_type != I_NxN &&
                mb->MbPartPredMode[0] != Intra_16x16 &&
                mb->NumMbPart == 4)
            {
                TRACE_3(MB, "---- macroblock_layer - mb partition & related\n");

                int mbPartIdx = 0;
                for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
                {
                    if (mb->sub_mb_type[mbPartIdx] != B_Direct_8x8)
                    {
                        if (NumSubMbPart(slice->slice_type, mb->sub_mb_type[mbPartIdx]) > 1)
                        {
                            noSubMbPartSizeLessThan8x8Flag = false;
                        }
                    }
                    else if (sps->direct_8x8_inference_flag == false)
                    {
                        noSubMbPartSizeLessThan8x8Flag = false;
                    }
                }

                // Read sub macroblock prediction mode
                sub_mb_pred(dc, mb->mb_type, mb->sub_mb_type);
            }
            else
#endif // ENABLE_INTER_PRED
            {
                TRACE_3(MB, "---- macroblock_layer - transform_size_8x8_flag & prediction modes\n");

                if (pps->transform_8x8_mode_flag == true && mb->mb_type == I_NxN)
                {
                    if (pps->entropy_coding_mode_flag)
                        mb->transform_size_8x8_flag = read_ae(dc, SE_transform_size_8x8_flag);
                    else
                        mb->transform_size_8x8_flag = read_bit(dc->bitstr);

                    // Need to update MbPartPredMode in order to detect I_8x8 prediction mode
                    mb->MbPartPredMode[0] = MbPartPredMode(mb, slice->slice_type, 0);
                }

                // Read macroblock prediction mode
                mb_pred(dc, mb);
            }

            if (mb->MbPartPredMode[0] != Intra_16x16)
            {
                TRACE_3(MB, "---- macroblock_layer - coded block pattern & transform_size_8x8_flag\n");

                if (pps->entropy_coding_mode_flag)
                    mb->coded_block_pattern = read_ae(dc, SE_coded_block_pattern);
                else
                    mb->coded_block_pattern = read_me(dc->bitstr, sps->ChromaArrayType, dc->IdrPicFlag);

                mb->CodedBlockPatternLuma = mb->coded_block_pattern % 16;
                mb->CodedBlockPatternChroma = mb->coded_block_pattern / 16;
#if ENABLE_INTER_PRED
                if (mb->CodedBlockPatternLuma > 0 &&
                    pps->transform_8x8_mode_flag == true &&
                    mb->mb_type != I_NxN &&
                    noSubMbPartSizeLessThan8x8Flag == true &&
                    (mb->mb_type != B_Direct_16x16 || sps->direct_8x8_inference_flag == true))
                {
                    if (pps->entropy_coding_mode_flag)
                        mb->transform_size_8x8_flag = read_ae(dc, SE_transform_size_8x8_flag);
                    else
                        mb->transform_size_8x8_flag = read_bit(dc->bitstr);

                    // Need to update MbPartPredMode in order to account for I_8x8 prediction mode
                    if (transform_size_8x8_flag)
                        mb->MbPartPredMode[0] = MbPartPredMode(mb, slice->slice_type, 0);
                }
#endif // ENABLE_INTER_PRED
            }

            if (mb->CodedBlockPatternLuma > 0 ||
                mb->CodedBlockPatternChroma > 0 ||
                mb->MbPartPredMode[0] == Intra_16x16)
            {
                TRACE_3(MB, "---- macroblock_layer - quantization parameter & residual datas\n");

                // Read QP delta
                if (pps->entropy_coding_mode_flag)
                    mb->mb_qp_delta = read_ae(dc, SE_mb_qp_delta);
                else
                    mb->mb_qp_delta = read_se(dc->bitstr);

                // Parse the residual coefficients
                ////////////////////////////////////////////////////////////////

                // Luma levels
                residual_luma(dc, 0, 15);

                // Chroma levels
                residual_chroma(dc, 0, 15);
            }
            else
            {
                TRACE_3(MB, "---- macroblock_layer - No residual datas to decode in this macroblock\n");
            }

            // Compute luma Quantization Parameters
            if (mb->mb_qp_delta)
                mb->QPY = ((slice->QPYprev + mb->mb_qp_delta + 52 + sps->QpBdOffsetY*2) % (52 + sps->QpBdOffsetY)) - sps->QpBdOffsetY;
            else
                mb->QPY = slice->QPYprev;

            mb->QPprimeY = mb->QPY + sps->QpBdOffsetY;
            slice->QPYprev = mb->QPY;

            // Set Transform Bypass Mode
            if (sps->qpprime_y_zero_transform_bypass_flag == true && mb->QPprimeY == 0)
                mb->TransformBypassModeFlag = true;

            // Prediction process (include quantization and transformation stages)
            ////////////////////////////////////////////////////////////////

            if (dc->IdrPicFlag)
            {
                retcode = intra_prediction_process(dc, mb);
            }
            else
            {
                retcode = inter_prediction_process(dc, mb);
            }

            // Print macroblock(s) header and block data ?
            ////////////////////////////////////////////////////////////////

#if ENABLE_DEBUG
            mb->mbFileAddrStop = bitstream_get_absolute_bit_offset(dc->bitstr) - 1;

            int frame_debug_range[2] = {-1, -1}; // Range of (idr) frame(s) to debug/analyse
            int mb_debug_range[2] = {-1, -1}; // Range of macroblock(s) to debug/analyse

            if (dc->idrCounter >= frame_debug_range[0] && dc->idrCounter <= frame_debug_range[1])
            {
                if (mb->mbAddr >= mb_debug_range[0] && mb->mbAddr <= mb_debug_range[1])
                {
                    print_macroblock_layer(dc, mb);
                    print_macroblock_pixel_residual(mb);
                    print_macroblock_pixel_predicted(mb);
                    print_macroblock_pixel_final(mb);
                }
            }
#endif // ENABLE_DEBUG
        }

        TRACE_3(MB, "---- macroblock_layer - the end\n\n");
    }

    return retcode;
}
Ejemplo n.º 2
0
/*!
 * \brief Read prediction informations for current macroblock.
 * \param *dc The current DecodingContext.
 * \param *mb The current macroblock.
 *
 * Intra prediction infos are a table containing prediction mode for each blocks.
 * Inter prediction infos are motion vectors.
 */
static void mb_pred(DecodingContext_t *dc, Macroblock_t *mb)
{
    TRACE_INFO(MB, "  > " BLD_GREEN "mb_pred()\n" CLR_RESET);

    if (mb->MbPartPredMode[0] == Intra_4x4 ||
        mb->MbPartPredMode[0] == Intra_8x8 ||
        mb->MbPartPredMode[0] == Intra_16x16)
    {
        if (mb->MbPartPredMode[0] == Intra_4x4)
        {
            // Read intra prediction mode for all 16 4x4 luma blocks
            unsigned int luma4x4BlkIdx = 0;
            for (luma4x4BlkIdx = 0; luma4x4BlkIdx < 16; luma4x4BlkIdx++)
            {
                if (dc->entropy_coding_mode_flag)
                    mb->prev_intra4x4_pred_mode_flag[luma4x4BlkIdx] = read_ae(dc, SE_prev_intraxxx_pred_mode_flag);
                else
                    mb->prev_intra4x4_pred_mode_flag[luma4x4BlkIdx] = read_bit(dc->bitstr);

                if (mb->prev_intra4x4_pred_mode_flag[luma4x4BlkIdx] == false)
                {
                    if (dc->entropy_coding_mode_flag)
                        mb->rem_intra4x4_pred_mode[luma4x4BlkIdx] = read_ae(dc, SE_rem_intraxxx_pred_mode);
                    else
                        mb->rem_intra4x4_pred_mode[luma4x4BlkIdx] = read_bits(dc->bitstr, 3);
                }
            }
        }
        else if (mb->MbPartPredMode[0] == Intra_8x8)
        {
            // Read intra prediction mode for all 4 8x8 luma blocks
            unsigned int luma8x8BlkIdx = 0;
            for (luma8x8BlkIdx = 0; luma8x8BlkIdx < 4; luma8x8BlkIdx++)
            {
                if (dc->entropy_coding_mode_flag)
                    mb->prev_intra8x8_pred_mode_flag[luma8x8BlkIdx] = read_ae(dc, SE_prev_intraxxx_pred_mode_flag);
                else
                    mb->prev_intra8x8_pred_mode_flag[luma8x8BlkIdx] = read_bit(dc->bitstr);

                if (mb->prev_intra8x8_pred_mode_flag[luma8x8BlkIdx] == false)
                {
                    if (dc->entropy_coding_mode_flag)
                        mb->rem_intra8x8_pred_mode[luma8x8BlkIdx] = read_ae(dc, SE_rem_intraxxx_pred_mode);
                    else
                        mb->rem_intra8x8_pred_mode[luma8x8BlkIdx] = read_bits(dc->bitstr, 3);
                }
            }
        }

        // Read intra prediction mode for chroma blocks
        if (dc->ChromaArrayType == 1 || dc->ChromaArrayType == 2)
        {
            if (dc->entropy_coding_mode_flag)
                mb->IntraChromaPredMode = read_ae(dc, SE_intra_chroma_pred_mode);
            else
                mb->IntraChromaPredMode = read_ue(dc->bitstr);
        }
    }
    else if (mb->MbPartPredMode[0] != Direct)
    {
        // ref_idx_l0
        unsigned int mbPartIdx = 0;
        for (mbPartIdx = 0; mbPartIdx < mb->NumMbPart; mbPartIdx++)
        {
            if ((dc->active_slice->num_ref_idx_l0_active_minus1 > 0 ||
                 dc->active_slice->mb_field_decoding_flag != dc->active_slice->field_pic_flag) &&
                MbPartPredMode(mb, dc->active_slice->slice_type, mbPartIdx) != Pred_L1)
            {
                if (dc->entropy_coding_mode_flag)
                    mb->ref_idx_l0[mbPartIdx] = read_ae(dc, SE_ref_idx_lx);
                else
                    mb->ref_idx_l0[mbPartIdx] = read_te(dc->bitstr, 0);
            }
        }

        // ref_idx_l1
        for (mbPartIdx = 0; mbPartIdx < mb->NumMbPart; mbPartIdx++)
        {
            if ((dc->active_slice->num_ref_idx_l1_active_minus1 > 0 ||
                 dc->active_slice->mb_field_decoding_flag != dc->active_slice->field_pic_flag) &&
                MbPartPredMode(mb, dc->active_slice->slice_type, mbPartIdx) != Pred_L0)
            {
                if (dc->entropy_coding_mode_flag)
                    mb->ref_idx_l1[mbPartIdx] = read_ae(dc, SE_ref_idx_lx);
                else
                    mb->ref_idx_l1[mbPartIdx] = read_te(dc->bitstr, 0);
            }
        }

        // mvd_l0
        for (mbPartIdx = 0; mbPartIdx < mb->NumMbPart; mbPartIdx++)
        {
            if (MbPartPredMode(mb, dc->active_slice->slice_type, mbPartIdx) != Pred_L1)
            {
                if (dc->entropy_coding_mode_flag)
                {
                    mb->mvd_l0[mbPartIdx][0][0] = read_ae(dc, SE_mvd_lx0);
                    mb->mvd_l0[mbPartIdx][0][1] = read_ae(dc, SE_mvd_lx1);
                }
                else
                {
                    mb->mvd_l0[mbPartIdx][0][0] = read_te(dc->bitstr, 0);
                    mb->mvd_l0[mbPartIdx][0][1] = read_te(dc->bitstr, 0);
                }
            }
        }

        // mvd_l1
        for (mbPartIdx = 0; mbPartIdx < mb->NumMbPart; mbPartIdx++)
        {
            if (MbPartPredMode(mb, dc->active_slice->slice_type, mbPartIdx) != Pred_L0)
            {
                if (dc->entropy_coding_mode_flag)
                {
                    mb->mvd_l1[mbPartIdx][0][0] = read_ae(dc, SE_mvd_lx0);
                    mb->mvd_l1[mbPartIdx][0][1] = read_ae(dc, SE_mvd_lx1);
                }
                else
                {
                    mb->mvd_l1[mbPartIdx][0][0] = read_te(dc->bitstr, 0);
                    mb->mvd_l1[mbPartIdx][0][1] = read_te(dc->bitstr, 0);
                }
            }
        }
    }
}
Ejemplo n.º 3
0
/*!
 * \param *dc The current DecodingContext.
 * \param mb_type The macroblock prediction type.
 * \param *sub_mb_type The sub macroblock prediction type.
 *
 * Find the sub macroblock prediction type (intra prediction mode or motion vectors exctraction).
 */
static void sub_mb_pred(DecodingContext_t *dc, const unsigned int mb_type, unsigned int *sub_mb_type)
{
    TRACE_INFO(MB, "  > " BLD_GREEN "sub_mb_pred()\n" CLR_RESET);

    // Shortcut
    Macroblock_t *mb = dc->mb_array[dc->CurrMbAddr];
    slice_t *slice = dc->active_slice;

    // Read sub_mb_type
    int mbPartIdx = 0;
    for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
    {
        if (dc->entropy_coding_mode_flag)
            sub_mb_type[mbPartIdx] = read_ae(dc, SE_sub_mb_type);
        else
            sub_mb_type[mbPartIdx] = read_ue(dc->bitstr);
    }

    // ref_idx_l0
    for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
    {
        if ((slice->num_ref_idx_l0_active_minus1 > 0 ||
             slice->mb_field_decoding_flag != slice->field_pic_flag) &&
            mb_type != P_8x8ref0 &&
            sub_mb_type[mbPartIdx] != B_Direct_8x8 &&
            SubMbPredMode(slice->slice_type, sub_mb_type[mbPartIdx]) != Pred_L1)
        {
            if (dc->entropy_coding_mode_flag)
                mb->ref_idx_l0[mbPartIdx] = read_ae(dc, SE_ref_idx_lx);
            else
                mb->ref_idx_l0[mbPartIdx] = read_te(dc->bitstr, 0);
        }
    }

    // ref_idx_l1
    for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
    {
        if ((slice->num_ref_idx_l1_active_minus1 > 0 ||
             slice->mb_field_decoding_flag != slice->field_pic_flag) &&
            sub_mb_type[mbPartIdx] != B_Direct_8x8 &&
            SubMbPredMode(slice->slice_type, sub_mb_type[mbPartIdx]) != Pred_L0)
        {
            if (dc->entropy_coding_mode_flag)
                mb->ref_idx_l1[mbPartIdx] = read_ae(dc, SE_ref_idx_lx);
            else
                mb->ref_idx_l1[mbPartIdx] = read_te(dc->bitstr, 0);
        }
    }

    // mvd_l0
    for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
    {
        if (sub_mb_type[mbPartIdx] != B_Direct_8x8 &&
            SubMbPredMode(slice->slice_type, sub_mb_type[mbPartIdx]) != Pred_L1)
        {
            int subMbPartIdx = 0;
            for (subMbPartIdx = 0; subMbPartIdx < NumSubMbPart(slice->slice_type, sub_mb_type[mbPartIdx]); subMbPartIdx++)
            {
                if (dc->entropy_coding_mode_flag)
                {
                    mb->mvd_l0[mbPartIdx][subMbPartIdx][0] = read_ae(dc, SE_mvd_lx0);
                    mb->mvd_l0[mbPartIdx][subMbPartIdx][1] = read_ae(dc, SE_mvd_lx1);
                }
                else
                {
                    mb->mvd_l0[mbPartIdx][subMbPartIdx][0] = read_se(dc->bitstr);
                    mb->mvd_l0[mbPartIdx][subMbPartIdx][1] = read_se(dc->bitstr);
                }
            }
        }
    }

    // mvd_l1
    for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
    {
        if (sub_mb_type[mbPartIdx] != B_Direct_8x8 &&
            SubMbPredMode(slice->slice_type, sub_mb_type[mbPartIdx]) != Pred_L0)
        {
            int subMbPartIdx = 0;
            for (subMbPartIdx = 0; subMbPartIdx < NumSubMbPart(slice->slice_type, sub_mb_type[mbPartIdx]); subMbPartIdx++)
            {
                if (dc->entropy_coding_mode_flag)
                {
                    mb->mvd_l1[mbPartIdx][subMbPartIdx][0] = read_ae(dc, SE_mvd_lx0);
                    mb->mvd_l1[mbPartIdx][subMbPartIdx][1] = read_ae(dc, SE_mvd_lx1);
                }
                else
                {
                    mb->mvd_l1[mbPartIdx][subMbPartIdx][0] = read_se(dc->bitstr);
                    mb->mvd_l1[mbPartIdx][subMbPartIdx][1] = read_se(dc->bitstr);
                }
            }
        }
    }
}
Ejemplo n.º 4
0
/*!
 * \param *dc The current DecodingContext.
 * \param *slice The current Slice.
 * \return 0 if an error occurred while decoding slice datas, 1 otherwise.
 */
static int decodeSliceData(DecodingContext_t *dc, slice_t *slice)
{
    TRACE_INFO(SLICE, "> " BLD_GREEN "decodeSliceData()\n" CLR_RESET);

    // Initialization
    int retcode = SUCCESS;
    dc->CurrMbAddr = 0;
    slice->moreDataFlag = true;
    slice->prevMbSkipped = false;

    // Shortcut
    pps_t *pps = dc->pps_array[slice->pic_parameter_set_id];

    // Slice data decoding
    ////////////////////////////////////////////////////////////////////////////

    if (pps->entropy_coding_mode_flag)
    {
        // CABAC alignment
        while (bitstream_check_alignment(dc->bitstr) == false)
        {
            if (read_bit(dc->bitstr) == 0) // cabac_alignment_one_bit
            {
                TRACE_ERROR(SLICE, "cabac_alignment_one_bit must be 1\n");
                return FAILURE;
            }
        }

        // CABAC initialization process
        initCabacContextVariables(dc);
        initCabacDecodingEngine(dc);
    }

    while ((retcode == SUCCESS) &&
           (slice->moreDataFlag == true) &&
           (dc->CurrMbAddr < dc->PicSizeInMbs))
    {
#if ENABLE_INTER_PRED
        // Only I frames are supported anyway
        if (slice->slice_type != 2 && slice->slice_type != 7 &&
            slice->slice_type != 4 && slice->slice_type != 9) // Not I or SI slice
        {
            if (pps->entropy_coding_mode_flag)
            {
                slice->mb_skip_flag = read_ae(dc, SE_mb_skip_flag);
                slice->moreDataFlag = !slice->mb_skip_flag;
            }
            else
            {
                int i = 0;
                slice->mb_skip_run = read_ue(dc->bitstr);
                slice->prevMbSkipped = (slice->mb_skip_run > 0);

                for (i = 0; i < slice->mb_skip_run; i++)
                {
                    dc->CurrMbAddr = NextMbAddress(dc, dc->CurrMbAddr);
                }

                if (slice->mb_skip_run > 0)
                {
                    slice->moreDataFlag = h264_more_rbsp_data(dc->bitstr);
                }
            }
        }

        // If there is still some data in the slice
        if (slice->moreDataFlag)
        {
#if ENABLE_MBAFF
            if (slice->MbaffFrameFlag == true &&
                (dc->CurrMbAddr % 2 == 0 || (dc->CurrMbAddr % 2 == 1 && slice->prevMbSkipped == true)))
            {
                if (pps->entropy_coding_mode_flag)
                    slice->mb_field_decoding_flag = read_ae(dc, SE_mb_field_decoding_flag);
                else
                    slice->mb_field_decoding_flag = read_bit(dc->bitstr);

                TRACE_ERROR(DSLICE, ">>> UNSUPPORTED (interlaced mode)\n");
                return UNSUPPORTED;
            }
#endif /* ENABLE_MBAFF */

            // Macroblock decoding
            retcode = macroblock_layer(dc, dc->CurrMbAddr);
        }
#endif /* ENABLE_INTER_PRED */

        // Macroblock decoding
        retcode = macroblock_layer(dc, dc->CurrMbAddr);

        // Check for end of slice
        if (pps->entropy_coding_mode_flag)
        {
#if ENABLE_INTER_PRED
            // Only I frames are supported anyway
            if (slice->slice_type != 2 && slice->slice_type != 7 &&
                slice->slice_type != 4 && slice->slice_type != 9) // Not I or SI slice
            {
                slice->prevMbSkipped = slice->mb_skip_flag;
            }

#if ENABLE_MBAFF
            // MbaffFrameFlag is unsupported, so always "false"
            if (slice->MbaffFrameFlag == true && dc->CurrMbAddr % 2 == 0)
            {
                slice->moreDataFlag = true;
            }
            else
#endif /* ENABLE_MBAFF */
#endif /* ENABLE_INTER_PRED */
            {
                slice->end_of_slice_flag = read_ae(dc, SE_end_of_slice_flag);
                if (slice->end_of_slice_flag)
                {
                    TRACE_INFO(SLICE, "end_of_slice_flag detected!\n");
                    slice->moreDataFlag = false;
                }
            }
        }
        else
        {
            slice->moreDataFlag = h264_more_rbsp_data(dc->bitstr);
        }

        // Get next macroblock address
        dc->CurrMbAddr = NextMbAddress(dc, dc->CurrMbAddr);
    }

    return retcode;
}