From d03d7187c1881237b1a98404a125507d33d85a0e Mon Sep 17 00:00:00 2001 From: Fox Caminiti Date: Sun, 21 Aug 2022 22:05:10 -0400 Subject: a bit of housekeeping --- ffmpeg_backend.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'ffmpeg_backend.cpp') diff --git a/ffmpeg_backend.cpp b/ffmpeg_backend.cpp index 03d3214..6e16e76 100644 --- a/ffmpeg_backend.cpp +++ b/ffmpeg_backend.cpp @@ -45,6 +45,9 @@ bool32 AV_TryFrame(av_info *AV, int32 *err) while (*err >= 0) { *err = avcodec_receive_frame(AV->VideoCodecContext, AV->VideoFrame); if (*err == AVERROR_EOF) { + av_seek_frame(AV->FileFormatContext, -1, 0, AVSEEK_FLAG_BACKWARD); + *err = 0; + break; } else if (*err == AVERROR(EAGAIN)) { *err = 0; break; @@ -209,6 +212,11 @@ void AV_GetPTSAverage(source *Source, av_info *AV, int32 *err) // TODO(fox): This PTS average isn't exact and causes an occasional // frame skip. See libav remarks in forum for more details. + if (AV->VideoStream->duration == 1) { + Source->Info.AvgPTSPerFrame = 1; + return; + } + // TODO(fox): Handle footage under five seconds. int16 TestAmount = 5; @@ -234,6 +242,53 @@ void AV_GetPTSAverage(source *Source, av_info *AV, int32 *err) av_seek_frame(AV->FileFormatContext, -1, 0, AVSEEK_FLAG_BACKWARD); } +cached_bitmap * AV_LoadStill(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory) +{ + av_info *AV = (av_info *)BitmapInfo->AVInfo; + int32 *CurrentlyRenderedFrame = &BitmapInfo->CurrentFrame; + + int32 err = 0; + + *CurrentlyRenderedFrame = 0; + + av_seek_frame(AV->FileFormatContext, -1, 0, AVSEEK_FLAG_FRAME); + + while (err >= 0) { + if (AV_TryFrame(AV, &err)) + { + uint16 Width = Source->Info.Width; + uint16 Height = Source->Info.Height; + uint16 BytesPerPixel = Source->Info.BytesPerPixel; + int32 Pitch = Width*BytesPerPixel; + + cached_bitmap *Bitmap = Memory_RollingBitmap(Memory, Source, 0); + void *Buffer = Bitmap->Data; + + int out_linesize[4] = { Pitch, Pitch, Pitch, Pitch }; + uint8 *dst_data[4] = { (uint8 *)Buffer, (uint8 *)Buffer + Width*Height*BytesPerPixel, + (uint8 *)Buffer + Width*Height*BytesPerPixel*2, (uint8 *)Buffer + Width*Height*BytesPerPixel*3 }; + + // NOTE(fox): This function will be replaced in the future. + AV->RGBContext = sws_getContext(AV->VideoFrame->width, AV->VideoFrame->height, (AVPixelFormat)AV->VideoFrame->format, + AV->VideoFrame->width, AV->VideoFrame->height, AV_PIX_FMT_RGBA, SWS_BILINEAR, + NULL, NULL, NULL); + + if(!AV->RGBContext) { + printf("Libav error: SwsContext creation failed."); + } + + sws_scale(AV->RGBContext, AV->VideoFrame->data, AV->VideoFrame->linesize, 0, AV->VideoFrame->height, + dst_data, out_linesize); + + av_frame_unref(AV->VideoFrame); + + Assert(BitmapInfo->BitmapBuffer); + return Bitmap; + } + av_frame_unref(AV->VideoFrame); + } + return 0; +} cached_bitmap * AV_LoadVideoFrame(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, int32 TimelineFrame) { -- cgit v1.2.3