Example #1
0
DecodingContext_t *h264_init(MediaFile_t *input_video, unsigned tid)
{
    TRACE_INFO(H264, BLD_GREEN "h264_init()" CLR_RESET);

    DecodingContext_t *dc = NULL;

    if (input_video == NULL)
    {
        TRACE_ERROR(H264, "MediaFile_t is NULL, exiting decoder");
    }
    else
    {
        // Init decoding context
        dc = initDecodingContext(input_video, tid);

        if (dc == NULL)
        {
            TRACE_ERROR(H264, "Unable to allocate DecodingContext_t, exiting decoder");
        }
        else
        {
            int error_count = 0;

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

            // Load "parameter sets"
            for (unsigned pid = 0; pid < dc->MediaFile->tracks_video[tid]->parameter_count; pid++)
            {
                int64_t samplesoffset = dc->MediaFile->tracks_video[tid]->parameter_offset[pid];
                int64_t samplesize = dc->MediaFile->tracks_video[tid]->parameter_size[pid];

                if (buffer_feed_manual(dc->bitstr, samplesoffset-1, samplesize+1) != SUCCESS)
                    error_count++;
                else
                    if (h264_decode_nalu(dc, samplesoffset, samplesize) != SUCCESS)
                        error_count++;
            }

            if (error_count != 0)
            {
                TRACE_ERROR(H264, "%i errors happened when decoding SPS and PPS content!", error_count);

                // Stop the decoding process and free resources
                dc->decoderRunning = false;
                freeDecodingContext(&dc);
            }
        }
    }

    return dc;
}
Example #2
0
void h264_cleanup(DecodingContext_t *dc)
{
    TRACE_INFO(H264, BLD_GREEN "h264_cleanup()" CLR_RESET);
    freeDecodingContext(&dc);
}
Example #3
0
/*!
 * \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;
}