summaryrefslogtreecommitdiff
path: root/ffmpeg_backend.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ffmpeg_backend.cpp')
-rw-r--r--ffmpeg_backend.cpp55
1 files changed, 55 insertions, 0 deletions
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)
{