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; }
/*! * \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; }