/// @brief Indexes the file /// @return The number of frames found in the file /// This function goes through the file, finds and parses all file and frame headers, /// and creates a seek table that lists the byte positions of all frames so seeking /// can easily be done. int YUV4MPEGVideoProvider::IndexFile() { int framecount = 0; // the ParseFileHeader() call in LoadVideo() will already have read // the file header for us and set the seek position correctly while (true) { int64_t curpos = ftello(sf); // update position if (curpos < 0) throw VideoOpenError("IndexFile: ftello failed"); // continue reading headers until no more are found std::vector<std::string> tags = ReadHeader(curpos); curpos = ftello(sf); if (curpos < 0) throw VideoOpenError("IndexFile: ftello failed"); if (tags.empty()) break; // no more headers Y4M_FrameFlags flags = Y4M_FFLAG_NOTSET; if (tags.front() == "YUV4MPEG2") { ParseFileHeader(tags); continue; } else if (tags.front() == "FRAME") flags = ParseFrameHeader(tags); if (flags == Y4M_FFLAG_NONE) { framecount++; seek_table.push_back(curpos); // seek to next frame header start position if (fseeko(sf, frame_sz, SEEK_CUR)) throw VideoOpenError("IndexFile: failed seeking to position " + std::to_string(curpos + frame_sz)); } else { /// @todo implement rff flags etc } } return framecount; }
//////////////////////////////////////////////////////////////////////////// /// /// Parse the frame header and store the results for when we emit the frame. /// FrameParserStatus_t FrameParser_AudioMlp_c::ReadHeaders( void ) { FrameParserStatus_t Status; // // Perform the common portion of the read headers function // FrameParser_Audio_c::ReadHeaders(); // Status = ParseFrameHeader( BufferData, &ParsedFrameHeader, BufferLength ); if( Status != FrameParserNoError ) { FRAME_ERROR("Failed to parse frame header, bad collator selected?\n"); return Status; } if (ParsedFrameHeader.Length != BufferLength) { FRAME_ERROR("Buffer length is inconsistant with frame header, bad collator selected?\n"); return FrameParserError; } FrameToDecode = true; if( CurrentStreamParameters.AccumulatedFrameNumber != ParsedFrameHeader.AudioFrameNumber ) { Status = GetNewStreamParameters( (void **) &StreamParameters ); if( Status != FrameParserNoError ) { FRAME_ERROR( "Cannot get new stream parameters\n" ); return Status; } StreamParameters->AccumulatedFrameNumber = ParsedFrameHeader.AudioFrameNumber; CurrentStreamParameters.AccumulatedFrameNumber = ParsedFrameHeader.AudioFrameNumber; UpdateStreamParameters = true; } Status = GetNewFrameParameters( (void **) &FrameParameters ); if( Status != FrameParserNoError ) { FRAME_ERROR( "Cannot get new frame parameters\n" ); return Status; } // Nick inserted some default values here ParsedFrameParameters->FirstParsedParametersForOutputFrame = true; ParsedFrameParameters->FirstParsedParametersAfterInputJump = FirstDecodeAfterInputJump; ParsedFrameParameters->SurplusDataInjected = SurplusDataInjected; ParsedFrameParameters->ContinuousReverseJump = ContinuousReverseJump; ParsedFrameParameters->KeyFrame = true; ParsedFrameParameters->ReferenceFrame = false; ParsedFrameParameters->NewFrameParameters = true; ParsedFrameParameters->SizeofFrameParameterStructure = sizeof(MlpAudioFrameParameters_t); ParsedFrameParameters->FrameParameterStructure = FrameParameters; ParsedAudioParameters->Source.BitsPerSample = 0; // filled in by codec ParsedAudioParameters->Source.ChannelCount = 0; // filled in by codec ParsedAudioParameters->Source.SampleRateHz = MlpSamplingFreq[ParsedFrameHeader.SamplingFrequency]; ParsedAudioParameters->SampleCount = ParsedFrameHeader.NumberOfSamples; ParsedAudioParameters->Organisation = 0; // filled in by codec return FrameParserNoError; }
//////////////////////////////////////////////////////////////////////////// /// /// Parse the frame header and store the results for when we emit the frame. /// FrameParserStatus_t FrameParser_AudioLpcm_c::ReadHeaders(void) { FrameParserStatus_t Status; LpcmAudioParsedFrameHeader_t ParsedFrameHeader; FRAME_DEBUG(">><<\n"); // // Perform the common portion of the read headers function // FrameParser_Audio_c::ReadHeaders(); // // the frame type is required to (re)parse the private data area ParsedFrameHeader.Type = StreamType; Status = ParseFrameHeader(BufferData, &ParsedFrameHeader, BufferLength); if (Status != FrameParserNoError) { FRAME_ERROR("Failed to parse frame header, bad collator selected?\n"); return Status; } if ((ParsedFrameHeader.Length + AudioPesPrivateDataLength[ParsedFrameHeader.Type]) != BufferLength) { FRAME_ERROR("Buffer length (%d) is inconsistent with frame header (%d), bad collator selected?\n", BufferLength, ParsedFrameHeader.Length); return FrameParserError; } FrameToDecode = true; Status = GetNewFrameParameters((void **) &FrameParameters); if (Status != FrameParserNoError) { FRAME_ERROR("Cannot get new frame parameters\n"); return Status; } // Nick inserted some default values here ParsedFrameParameters->FirstParsedParametersForOutputFrame = true; ParsedFrameParameters->FirstParsedParametersAfterInputJump = FirstDecodeAfterInputJump; ParsedFrameParameters->SurplusDataInjected = SurplusDataInjected; ParsedFrameParameters->ContinuousReverseJump = ContinuousReverseJump; ParsedFrameParameters->KeyFrame = true; ParsedFrameParameters->ReferenceFrame = false; ParsedFrameParameters->NewFrameParameters = true; ParsedFrameParameters->SizeofFrameParameterStructure = sizeof(LpcmAudioFrameParameters_t); ParsedFrameParameters->FrameParameterStructure = FrameParameters; FrameParameters->DrcCode = ParsedFrameHeader.DrcCode; FrameParameters->NumberOfSamples = ParsedFrameHeader.NumberOfSamples; ParsedFrameParameters->DataOffset = AudioPesPrivateDataLength[ParsedFrameHeader.Type]; // A SetGlobal Comand needs to be sent to update the frame parameters, // if some important part of the frame have been modified if ((CurrentStreamParameters.WordSize1 != ParsedFrameHeader.WordSize1) || (CurrentStreamParameters.EmphasisFlag != ParsedFrameHeader.EmphasisFlag) || (CurrentStreamParameters.MuteFlag != ParsedFrameHeader.MuteFlag) || (CurrentStreamParameters.NumberOfChannels != ParsedFrameHeader.NumberOfChannels) || (CurrentStreamParameters.SamplingFrequency1 != ParsedFrameHeader.SamplingFrequency1) || (CurrentStreamParameters.Type == TypeLpcmInvalid)) { UpdateStreamParameters = true; Status = GetNewStreamParameters((void **) &StreamParameters); if (Status != FrameParserNoError) { FRAME_ERROR("Cannot get new stream parameters\n"); return Status; } memcpy(StreamParameters, &ParsedFrameHeader, sizeof(LpcmAudioStreamParameters_t)); memcpy(&CurrentStreamParameters, &ParsedFrameHeader, sizeof(LpcmAudioStreamParameters_t)); } else { UpdateStreamParameters = false; } ParsedAudioParameters->Source.BitsPerSample = 0; // filled in by codec ParsedAudioParameters->Source.ChannelCount = 0; // filled in by codec ParsedAudioParameters->Source.SampleRateHz = LpcmDVDSamplingFreq[ParsedFrameHeader.SamplingFrequency1]; ParsedAudioParameters->SampleCount = ParsedFrameHeader.NumberOfSamples; ParsedAudioParameters->Organisation = 0; // filled in by codec return FrameParserNoError; }
//////////////////////////////////////////////////////////////////////////// /// /// Parse the frame header and store the results for when we emit the frame. /// FrameParserStatus_t FrameParser_AudioAac_c::ReadHeaders(void) { FrameParserStatus_t Status; // // Perform the common portion of the read headers function // FrameParser_Audio_c::ReadHeaders(); // // save the previous frame parameters AacAudioParsedFrameHeader_t LastParsedFrameHeader; memcpy(&LastParsedFrameHeader, &ParsedFrameHeader, sizeof(AacAudioParsedFrameHeader_t)); Status = ParseFrameHeader(BufferData, &ParsedFrameHeader, BufferLength, AAC_GET_FRAME_PROPERTIES, true); if (Status != FrameParserNoError) { if (Status == FrameParserHeaderUnplayable) { NumHeaderUnplayableErrors++; if (NumHeaderUnplayableErrors >= UnplayabilityThreshold) { // this is clearly not a passing bit error FRAME_ERROR("Too many unplayability reports, marking stream unplayable\n"); Player->MarkStreamUnPlayable(Stream); } } else { FRAME_ERROR("Failed to parse frame header, bad collator selected?\n"); } return Status; } if (ParsedFrameHeader.Length != BufferLength) { FRAME_ERROR("Buffer length is inconsistent with frame header, bad collator selected?\n"); return FrameParserError; } if (isFirstFrame) { isFirstFrame = false; FRAME_TRACE("AAC Frame type: %s, FrameSize %d, Number of samples: %d, SamplingFrequency %d, \n", FrameTypeName[ParsedFrameHeader.Type], ParsedFrameHeader.Length, ParsedFrameHeader.NumberOfSamples, ParsedFrameHeader.SamplingFrequency); } if ((ParsedFrameHeader.SamplingFrequency == 0) || (ParsedFrameHeader.NumberOfSamples == 0)) { // the current frame has no such properties, we must refer to the previous frame... if ((LastParsedFrameHeader.SamplingFrequency == 0) || (LastParsedFrameHeader.NumberOfSamples == 0)) { // the previous frame has no properties either, we cannot decode this frame... FrameToDecode = false; FRAME_ERROR("This frame should not be sent for decode (it relies on previous frame for audio parameters)\n"); return FrameParserError; } else { FrameToDecode = true; // make the previous frame properties the current ones.. memcpy(&ParsedFrameHeader, &LastParsedFrameHeader, sizeof(AacAudioParsedFrameHeader_t)); } } else { FrameToDecode = true; } NumHeaderUnplayableErrors = 0; Status = GetNewFrameParameters((void **) &FrameParameters); if (Status != FrameParserNoError) { FRAME_ERROR("Cannot get new frame parameters\n"); return Status; } // Nick inserted some default values here ParsedFrameParameters->FirstParsedParametersForOutputFrame = true; ParsedFrameParameters->FirstParsedParametersAfterInputJump = FirstDecodeAfterInputJump; ParsedFrameParameters->SurplusDataInjected = SurplusDataInjected; ParsedFrameParameters->ContinuousReverseJump = ContinuousReverseJump; ParsedFrameParameters->KeyFrame = true; ParsedFrameParameters->ReferenceFrame = false; ParsedFrameParameters->NewFrameParameters = true; ParsedFrameParameters->SizeofFrameParameterStructure = sizeof(AacAudioFrameParameters_t); ParsedFrameParameters->FrameParameterStructure = FrameParameters; FrameParameters->FrameSize = ParsedFrameHeader.Length; FrameParameters->Type = ParsedFrameHeader.Type; ParsedAudioParameters->Source.BitsPerSample = 0; // filled in by codec ParsedAudioParameters->Source.ChannelCount = 0; // filled in by codec ParsedAudioParameters->Source.SampleRateHz = ParsedFrameHeader.SamplingFrequency; ParsedAudioParameters->SampleCount = ParsedFrameHeader.NumberOfSamples; ParsedAudioParameters->Organisation = 0; // filled in by codec return FrameParserNoError; }
//////////////////////////////////////////////////////////////////////////// /// /// Parse the frame header and store the results for when we emit the frame. /// FrameParserStatus_t FrameParser_AudioAvs_c::ReadHeaders( void ) { FrameParserStatus_t Status; unsigned int ExtensionLength; // // Perform the common portion of the read headers function // FrameParser_Audio_c::ReadHeaders(); // Status = ParseFrameHeader( BufferData, &ParsedFrameHeader ); if( Status != FrameParserNoError ) { FRAME_ERROR("Failed to parse frame header, bad collator selected?\n"); return Status; } if (ParsedFrameHeader.Length != BufferLength) { // if the length is wrong that might be because we haven't considered any extensions Status = ParseExtensionHeader( BufferData + ParsedFrameHeader.Length, &ExtensionLength ); if( ( Status != FrameParserNoError ) || ( ParsedFrameHeader.Length + ExtensionLength != BufferLength ) ) { FRAME_ERROR("Buffer length is inconsistant with frame header, bad collator selected?\n"); return FrameParserError; } // that was it, adjust the recorded frame length accordingly ParsedFrameHeader.Length += ExtensionLength; } FrameToDecode = true; if( CurrentStreamParameters.Layer != ParsedFrameHeader.Layer ) { Status = GetNewStreamParameters( (void **) &StreamParameters ); if( Status != FrameParserNoError ) { FRAME_ERROR( "Cannot get new stream parameters\n" ); return Status; } StreamParameters->Layer = CurrentStreamParameters.Layer = ParsedFrameHeader.Layer; UpdateStreamParameters = true; } Status = GetNewFrameParameters( (void **) &FrameParameters ); if( Status != FrameParserNoError ) { FRAME_ERROR( "Cannot get new frame parameters\n" ); return Status; } // Nick inserted some default values here ParsedFrameParameters->FirstParsedParametersForOutputFrame = true; ParsedFrameParameters->FirstParsedParametersAfterInputJump = FirstDecodeAfterInputJump; ParsedFrameParameters->SurplusDataInjected = SurplusDataInjected; ParsedFrameParameters->ContinuousReverseJump = ContinuousReverseJump; ParsedFrameParameters->KeyFrame = true; ParsedFrameParameters->ReferenceFrame = false; ParsedFrameParameters->NewFrameParameters = true; ParsedFrameParameters->SizeofFrameParameterStructure = sizeof(MpegAudioFrameParameters_t); ParsedFrameParameters->FrameParameterStructure = FrameParameters; // this does look a little pointless but I don't want to trash it until we // have got a few more audio formats supported (see \todo in mpeg_audio.h). FrameParameters->BitRate = ParsedFrameHeader.BitRate; FrameParameters->FrameSize = ParsedFrameHeader.Length; ParsedAudioParameters->Source.BitsPerSample = 0; // filled in by codec ParsedAudioParameters->Source.ChannelCount = 0; // filled in by codec ParsedAudioParameters->Source.SampleRateHz = ParsedFrameHeader.SamplingFrequency; ParsedAudioParameters->SampleCount = ParsedFrameHeader.NumberOfSamples; ParsedAudioParameters->Organisation = 0; // filled in by codec return FrameParserNoError; }