bool VaapiDecoderH264::decodeCodecData(uint8_t * buf, uint32_t bufSize)
{
    Decode_Status status;
    H264NalUnit nalu;
    H264ParserResult result;
    uint32_t i, ofs, numSPS, numPPS;

    DEBUG("H264: codec data detected");

    if (!buf || bufSize == 0)
        return false;

    if (bufSize < 8)
        return false;

    if (buf[0] != 1) {
        ERROR("failed to decode codec-data, not in avcC format");
        return false;
    }

    m_nalLengthSize = (buf[4] & 0x03) + 1;

    numSPS = buf[5] & 0x1f;
    ofs = 6;

    for (i = 0; i < numSPS; i++) {
        result = h264_parser_identify_nalu_avc(&m_parser,
                                               buf, ofs, bufSize, 2,
                                               &nalu);
        if (result != H264_PARSER_OK)
            return false;

        status = decodeSPS(&nalu);
        if (status != DECODE_SUCCESS)
            return false;
        ofs = nalu.offset + nalu.size;
    }

    numPPS = buf[ofs];
    ofs++;

    for (i = 0; i < numPPS; i++) {
        result = h264_parser_identify_nalu_avc(&m_parser,
                                               buf, ofs, bufSize, 2,
                                               &nalu);
        if (result != H264_PARSER_OK)
            return false;

        status = decodePPS(&nalu);
        if (status != DECODE_SUCCESS)
            return false;
        ofs = nalu.offset + nalu.size;
    }

    m_isAVC = true;
    return true;
}
Decode_Status VaapiDecoderH264::decodeNalu(H264NalUnit * nalu)
{
    Decode_Status status;

    switch (nalu->type) {
    case H264_NAL_SLICE_IDR:
        /* fall-through. IDR specifics are handled in initPicture() */
    case H264_NAL_SLICE:
        if (!m_gotSPS || !m_gotPPS)
            return DECODE_SUCCESS;
        status = decodeSlice(nalu);
        break;
    case H264_NAL_SPS:
        status = decodeSPS(nalu);
        break;
    case H264_NAL_PPS:
        status = decodePPS(nalu);
        break;
    case H264_NAL_SEI:
        status = decodeSEI(nalu);
        break;
    case H264_NAL_SEQ_END:
        status = decodeSequenceEnd();
        break;
    case H264_NAL_AU_DELIMITER:
        /* skip all Access Unit NALs */
        status = DECODE_SUCCESS;
        break;
    case H264_NAL_FILLER_DATA:
        /* skip all Filler Data NALs */
        status = DECODE_SUCCESS;
        break;
    default:
        WARNING("unsupported NAL unit type %d", nalu->type);
        status = DECODE_PARSER_FAIL;
        break;
    }

    return status;
}
예제 #3
0
파일: h264.c 프로젝트: seanvk/MiniVideo
/*!
 * \brief Decode H.264 bitsream.
 * \param *input_video A pointer to a VideoFile_t structure, containing every informations available about the current video file.
 * \param *output_directory The directory where to save exported pictures.
 * \param picture_format The picture file format.
 * \param picture_quality The quality we want for exported picture [1;100].
 * \param picture_number The number of thumbnail(s) we want to extract.
 * \param picture_extractionmode The method of distribution for thumbnails extraction.
 * \return 1 if succeed, 0 otherwise.
 *
 * This decoder is based on the 'ITU-T H.264' recommendation:
 * 'Advanced Video Coding for generic audiovisual services'
 * It also correspond to 'ISO/IEC 14496-10' international standard, part 10:
 * 'Advanced Video Coding'.
 *
 * You can download the H.264 specification for free on the ITU website:
 * http://www.itu.int/rec/T-REC-H.264
 *
 * The very first step to H.264 bitstream decoding. Initialize DecodingContext,
 * then start the decoding process, which loop on NAL Units found in the bitstream.
 * Each NAL Unit is processed following it's content type.
 */
int h264_decode(VideoFile_t *input_video,
                const char *output_directory,
                const int picture_format,
                const int picture_quality,
                const int picture_number,
                const int picture_extractionmode)
{
    TRACE_INFO(H264, BLD_GREEN "h264_decode()\n" CLR_RESET);
    int retcode = FAILURE;

    // Init decoding context
    DecodingContext_t *dc = initDecodingContext(input_video);

    if (dc == NULL)
    {
        TRACE_ERROR(H264, "Unable to allocate DecodingContext_t, exiting decoder\n");
        return retcode;
    }
    else
    {
        // Init some quantization parameters
        computeNormAdjust(dc);

        // Init some export parameters
        //strncpy(dc->output_directory, output_directory, sizeof(output_directory));
        dc->output_format = picture_format;
        dc->picture_quality = picture_quality;
        dc->picture_number = picture_number;
        dc->picture_extractionmode = picture_extractionmode;

        // Start the decoding process
        dc->decoderRunning = true;
    }

    // Loop until end of file
    while (dc->decoderRunning)
    {
        // Load next NAL Unit
        retcode = buffer_feed_next_sample(dc->bitstr);

        // Check header validity
        if (nalu_parse_header(dc->bitstr, dc->active_nalu))
        {
            // Decode NAL Unit content
            switch (dc->active_nalu->nal_unit_type)
            {
            case NALU_TYPE_SLICE: // 1
            {
                TRACE_1(NALU, "This decoder only support IDR slice decoding!\n");
            }
            break;

            case NALU_TYPE_IDR: // 5
            {
                dc->IdrPicFlag = true;
                nalu_clean_sample(dc->bitstr);

                TRACE_INFO(MAIN, "> " BLD_GREEN "decodeIDR(%i)\n" CLR_RESET, dc->idrCounter);

                if (decode_slice(dc))
                {
                    retcode = SUCCESS;
                    dc->errorCounter = 0;
                    dc->idrCounter++;
                    dc->frameCounter++;
                }
                else
                    dc->errorCounter++;

                dc->IdrPicFlag = false;
            }
            break;

            case NALU_TYPE_SEI: // 6
            {
                nalu_clean_sample(dc->bitstr);

                if (decodeSEI(dc))
                {
                    retcode = SUCCESS;
                    printSEI(dc);
                }
                else
                    dc->errorCounter++;
            }
            break;

            case NALU_TYPE_SPS: // 7
            {
                nalu_clean_sample(dc->bitstr);

                if (decodeSPS(dc))
                {
                    retcode = SUCCESS;
                    printSPS(dc);
                }
                else
                    dc->errorCounter++;
            }
            break;

            case NALU_TYPE_PPS: // 8
            {
                nalu_clean_sample(dc->bitstr);

                if (decodePPS(dc))
                {
                    retcode = SUCCESS;
                    printPPS(dc);
                }
                else
                    dc->errorCounter++;
            }
            break;

            default:
            {
                dc->errorCounter++;
                TRACE_ERROR(NALU, "Unsupported NAL Unit! (nal_unit_type %i)\n", dc->active_nalu->nal_unit_type);
            }
            break;
            }

            // Reset NAL Unit structure
            nalu_reset(dc->active_nalu);
        }
        else
        {
            dc->errorCounter++;
            TRACE_WARNING(NALU, "No valid NAL Unit to decode! (errorCounter = %i)\n", dc->errorCounter);
        }

        if (dc->idrCounter == picture_number)
        {
            TRACE_INFO(H264, ">> " BLD_YELLOW "Decoding of %i IDR successfull!\n" CLR_RESET, dc->idrCounter);
            TRACE_INFO(H264, "H.264 decoding ended\n");
            retcode = SUCCESS;
            dc->decoderRunning = false;
        }

        if (dc->errorCounter > 64 || retcode == FAILURE)
        {
            TRACE_ERROR(H264, "Error inside NAL Unit decoding loop! (errorCounter = %i) (current nal_unit_type = %i)\n", dc->errorCounter, dc->active_nalu->nal_unit_type);
            TRACE_ERROR(H264, "H.264 decoding aborted\n");
            retcode = FAILURE;
            dc->decoderRunning = false;
        }
    }

    // Destroy decoding context
    freeDecodingContext(&dc);

    // Exit decoder
    return retcode;
}