void FillAP(FFMS_AudioProperties &AP, AVCodecContext *CTX, FFMS_Track &Frames) { AP.SampleFormat = static_cast<FFMS_SampleFormat>(CTX->sample_fmt); AP.BitsPerSample = av_get_bytes_per_sample(CTX->sample_fmt) * 8; AP.Channels = CTX->channels;; AP.ChannelLayout = CTX->channel_layout; AP.SampleRate = CTX->sample_rate; if (Frames.size() > 0) { AP.NumSamples = (Frames.back()).SampleStart + (Frames.back()).SampleCount; AP.FirstTime = ((Frames.front().PTS * Frames.TB.Num) / (double)Frames.TB.Den) / 1000; AP.LastTime = ((Frames.back().PTS * Frames.TB.Num) / (double)Frames.TB.Den) / 1000; } }
size_t GetSeekablePacketNumber(FFMS_Track const& Frames, size_t PacketNumber) { // Packets don't always have unique PTSes, so we may not be able to // uniquely identify the packet we want. This function attempts to find // a PTS we can seek to which will let us figure out which packet we're // on before we get to the packet we actually wanted // MatroskaAudioSource doesn't need this, as it seeks by byte offset // rather than PTS. LAVF theoretically can seek by byte offset, but we // don't use it as not all demuxers support it and it's broken in some of // those that claim to support it // However much we might wish to, we can't seek to before packet zero if (PacketNumber == 0) return PacketNumber; // Desired packet's PTS is unique, so don't do anything if (Frames[PacketNumber].PTS != Frames[PacketNumber - 1].PTS && (PacketNumber + 1 == Frames.size() || Frames[PacketNumber].PTS != Frames[PacketNumber + 1].PTS)) return PacketNumber; // When decoding, we only reliably know what packet we're at when the // newly parsed packet has a different PTS from the previous one. As such, // we walk backwards until we hit a different PTS and then seek to there, // so that we can then decode until we hit the PTS group we actually wanted // (and thereby know that we're at the first packet in the group rather // than whatever the splitter happened to choose) // This doesn't work if our desired packet has the same PTS as the first // packet, but this scenario should never come up anyway; we permanently // cache the decoded results from those packets, so there's no need to ever // seek to them int64_t PTS = Frames[PacketNumber].PTS; while (PacketNumber > 0 && PTS == Frames[PacketNumber].PTS) --PacketNumber; return PacketNumber; }