Beispiel #1
0
void FFMatroskaVideo::DecodeNextFrame() {
	if (HasPendingDelayedFrames()) return;

	AVPacket Packet;
	InitNullPacket(Packet);

	while (PacketNumber < Frames.size()) {
		// The additional indirection is because the packets are stored in
		// presentation order and not decoding order, this is unnoticeable
		// in the other sources where less is done manually
		const TFrameInfo &FI = Frames[Frames[PacketNumber].OriginalPos];
		unsigned int FrameSize = FI.FrameSize;
		ReadFrame(FI.FilePos, FrameSize, TCC.get(), MC);

		Packet.data = MC.Buffer;
		Packet.size = FrameSize;
		Packet.flags = FI.KeyFrame ? AV_PKT_FLAG_KEY : 0;

		PacketNumber++;

		if (DecodePacket(&Packet))
			return;
	}

	FlushFinalFrames();
}
Beispiel #2
0
void FFLAVFVideo::DecodeNextFrame(int64_t *AStartTime, int64_t *Pos) {
	*AStartTime = -1;
	if (HasPendingDelayedFrames()) return;

	AVPacket Packet;
	InitNullPacket(Packet);

	while (av_read_frame(FormatContext, &Packet) >= 0) {
		if (Packet.stream_index != VideoTrack) {
			av_free_packet(&Packet);
			continue;
		}

		if (*AStartTime < 0)
			*AStartTime = Frames.UseDTS ? Packet.dts : Packet.pts;

		if (*Pos < 0)
			*Pos = Packet.pos;

		bool FrameFinished = DecodePacket(&Packet);
		av_free_packet(&Packet);
		if (FrameFinished) return;
	}

	FlushFinalFrames();
}
Beispiel #3
0
bool FFMatroskaAudio::ReadPacket(AVPacket *Packet) {
	unsigned int FrameSize = CurrentFrame->FrameSize;
	ReadFrame(CurrentFrame->FilePos, FrameSize, TCC.get(), MC);
	InitNullPacket(*Packet);
	Packet->data = MC.Buffer;
	Packet->size = FrameSize;
	Packet->flags = CurrentFrame->KeyFrame ? AV_PKT_FLAG_KEY : 0;

	return true;
}
Beispiel #4
0
void FFHaaliVideo::DecodeNextFrame(int64_t *AFirstStartTime) {
	*AFirstStartTime = -1;
	if (HasPendingDelayedFrames()) return;

	AVPacket Packet;
	InitNullPacket(Packet);

	for (;;) {
		CComPtr<IMMFrame> pMMF;
		if (pMMC->ReadFrame(NULL, &pMMF) != S_OK)
			break;

		if (pMMF->GetTrack() != VideoTrack)
			continue;

		REFERENCE_TIME  Ts, Te;
		if (*AFirstStartTime < 0 && SUCCEEDED(pMMF->GetTime(&Ts, &Te)))
			*AFirstStartTime = Ts;

		BYTE *Data = NULL;
		if (FAILED(pMMF->GetPointer(&Data)))
			return;

		// align input data
		Packet.size = pMMF->GetActualDataLength();
		Packet.data = static_cast<uint8_t *>(av_mallocz(Packet.size + FF_INPUT_BUFFER_PADDING_SIZE));
		uint8_t *OriginalData = Packet.data;
		memcpy(Packet.data, Data, Packet.size);
		Packet.flags = pMMF->IsSyncPoint() == S_OK ? AV_PKT_FLAG_KEY : 0;

		AVBitStreamFilterContext *bsf = BitStreamFilter;
		while (bsf) {
			av_bitstream_filter_filter(bsf, CodecContext, NULL, &Packet.data,
				&Packet.size, Data, Packet.size, Packet.flags & AV_PKT_FLAG_KEY);
			bsf = bsf->next;
		}

		bool FrameFinished = DecodePacket(&Packet);

		// av_bitstream_filter_filter() can, if it feels like it, reallocate the input buffer and change the pointer.
		// If it does that, we need to free both the input buffer we allocated ourselves and the buffer lavc allocated.
		if (Packet.data != OriginalData) {
			av_free(Packet.data);
			Packet.data = OriginalData;
		}
		av_free(Packet.data);

		if (FrameFinished)
			return;
	}

	FlushFinalFrames();
}
Beispiel #5
0
bool FFLAVFAudio::ReadPacket(AVPacket *Packet) {
    InitNullPacket(*Packet);

    while (av_read_frame(FormatContext, Packet) >= 0) {
        if (Packet->stream_index == TrackNumber) {
            // Required because not all audio packets, especially in ogg, have a pts. Use the previous valid packet's pts instead.
            if (Packet->pts == AV_NOPTS_VALUE)
                Packet->pts = LastValidTS;
            else
                LastValidTS = Packet->pts;

            // This only happens if a really shitty demuxer seeks to a packet without pts *hrm* ogg *hrm* so read until a valid pts is reached
            int64_t PacketTS = Frames.HasTS ? Packet->pts : Packet->pos;
            if (PacketTS != AV_NOPTS_VALUE) {
                while (PacketNumber > 0 && FrameTS(PacketNumber) > PacketTS) --PacketNumber;
                while (FrameTS(PacketNumber) < PacketTS) ++PacketNumber;
                return true;
            }
        }
        av_free_packet(Packet);
    }
    return false;
}
FFMS_Index *FFLAVFIndexer::DoIndexing() {
	std::vector<SharedAudioContext> AudioContexts(FormatContext->nb_streams, SharedAudioContext(false));
	std::vector<SharedVideoContext> VideoContexts(FormatContext->nb_streams, SharedVideoContext(false));

	std::auto_ptr<FFMS_Index> TrackIndices(new FFMS_Index(Filesize, Digest));
	TrackIndices->Decoder = FFMS_SOURCE_LAVF;

	for (unsigned int i = 0; i < FormatContext->nb_streams; i++) {
		TrackIndices->push_back(FFMS_Track((int64_t)FormatContext->streams[i]->time_base.num * 1000,
			FormatContext->streams[i]->time_base.den,
			static_cast<FFMS_TrackType>(FormatContext->streams[i]->codec->codec_type)));

		if (FormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
			AVCodec *VideoCodec = avcodec_find_decoder(FormatContext->streams[i]->codec->codec_id);
			if (!VideoCodec)
				throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_UNSUPPORTED,
					"Video codec not found");

			if (avcodec_open2(FormatContext->streams[i]->codec, VideoCodec, NULL) < 0)
				throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_DECODING,
					"Could not open video codec");

			VideoContexts[i].CodecContext = FormatContext->streams[i]->codec;
			VideoContexts[i].Parser = av_parser_init(FormatContext->streams[i]->codec->codec_id);
			if (VideoContexts[i].Parser)
				VideoContexts[i].Parser->flags = PARSER_FLAG_COMPLETE_FRAMES;
			IndexMask |= 1 << i;
		}
		else if (IndexMask & (1 << i) && FormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
			AVCodecContext *AudioCodecContext = FormatContext->streams[i]->codec;

			AVCodec *AudioCodec = avcodec_find_decoder(AudioCodecContext->codec_id);
			if (AudioCodec == NULL)
				throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_UNSUPPORTED,
					"Audio codec not found");

			if (avcodec_open2(AudioCodecContext, AudioCodec, NULL) < 0)
				throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_DECODING,
					"Could not open audio codec");

			AudioContexts[i].CodecContext = AudioCodecContext;
		} else {
			IndexMask &= ~(1 << i);
		}
	}

	AVPacket Packet;
	InitNullPacket(Packet);
	std::vector<int64_t> LastValidTS(FormatContext->nb_streams, ffms_av_nopts_value);
	std::vector<int> LastDuration(FormatContext->nb_streams, 0);

#if (LIBAVFORMAT_VERSION_INT) < (AV_VERSION_INT(52,106,0))
	int64_t filesize = FormatContext->file_size;
#else
	int64_t filesize = avio_size(FormatContext->pb);
#endif
	while (av_read_frame(FormatContext, &Packet) >= 0) {
		// Update progress
		// FormatContext->pb can apparently be NULL when opening images.
		if (IC && FormatContext->pb) {
			if ((*IC)(FormatContext->pb->pos, filesize, ICPrivate))
				throw FFMS_Exception(FFMS_ERROR_CANCELLED, FFMS_ERROR_USER,
					"Cancelled by user");
		}
		if (!(IndexMask & (1 << Packet.stream_index))) {
			av_free_packet(&Packet);
			continue;
		}

		int Track = Packet.stream_index;
		bool KeyFrame = !!(Packet.flags & AV_PKT_FLAG_KEY);
		ReadTS(Packet, LastValidTS[Track], (*TrackIndices)[Track].UseDTS);

		if (FormatContext->streams[Track]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
			int64_t PTS = LastValidTS[Track];
			if (PTS == ffms_av_nopts_value) {
				if (Packet.duration == 0)
					throw FFMS_Exception(FFMS_ERROR_INDEXING, FFMS_ERROR_PARSER,
						"Invalid initial pts, dts, and duration");

				if ((*TrackIndices)[Track].empty())
					PTS = 0;
				else
					PTS = (*TrackIndices)[Track].back().PTS + LastDuration[Track];

				(*TrackIndices)[Track].HasTS = false;
				LastDuration[Track] = Packet.duration;
			}

			int RepeatPict = -1;
			int FrameType = 0;
			ParseVideoPacket(VideoContexts[Track], Packet, &RepeatPict, &FrameType);

			(*TrackIndices)[Track].push_back(TFrameInfo::VideoFrameInfo(PTS, RepeatPict, KeyFrame, FrameType, Packet.pos));
		}
		else if (FormatContext->streams[Track]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
			int64_t StartSample = AudioContexts[Track].CurrentSample;
			int64_t SampleCount = IndexAudioPacket(Track, &Packet, AudioContexts[Track], *TrackIndices);

			if (SampleCount != 0)
				(*TrackIndices)[Track].push_back(TFrameInfo::AudioFrameInfo(LastValidTS[Track],
					StartSample, SampleCount, KeyFrame, Packet.pos));
		}

		av_free_packet(&Packet);
	}

	TrackIndices->Sort();
	return TrackIndices.release();
}
void FFMS_VideoSource::FlushFinalFrames() {
	AVPacket Packet;
	InitNullPacket(Packet);
	DecodePacket(&Packet);
}