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