summaryrefslogtreecommitdiff
path: root/ffmpeg_backend.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ffmpeg_backend.cpp')
-rw-r--r--ffmpeg_backend.cpp169
1 files changed, 93 insertions, 76 deletions
diff --git a/ffmpeg_backend.cpp b/ffmpeg_backend.cpp
index e97b4da..dfc1241 100644
--- a/ffmpeg_backend.cpp
+++ b/ffmpeg_backend.cpp
@@ -19,20 +19,20 @@ av_always_inline std::string av_err2string(int errnum) {
#include "ffmpeg_backend.h"
-bool32 AV_TryFrame(av_codec_info *AV, av_packet_info *AVLayer, int32 *err)
+bool32 AV_TryFrame(av_info *AV, int32 *err)
{
- *err = av_read_frame(AV->FileFormatContext, AVLayer->VideoPacket);
- if (*err >= 0 && AVLayer->VideoPacket->stream_index != AV->VideoStream->index) {
- av_packet_unref(AVLayer->VideoPacket);
+ *err = av_read_frame(AV->FileFormatContext, AV->VideoPacket);
+ if (*err >= 0 && AV->VideoPacket->stream_index != AV->VideoStream->index) {
+ av_packet_unref(AV->VideoPacket);
return 0;
}
if (*err < 0)
- *err = avcodec_send_packet(AV->VideoCodecContext, AVLayer->VideoPacket);
+ *err = avcodec_send_packet(AV->VideoCodecContext, AV->VideoPacket);
else {
- *err = avcodec_send_packet(AV->VideoCodecContext, AVLayer->VideoPacket);
+ *err = avcodec_send_packet(AV->VideoCodecContext, AV->VideoPacket);
}
- av_packet_unref(AVLayer->VideoPacket);
+ av_packet_unref(AV->VideoPacket);
if (*err < 0)
{
@@ -41,7 +41,7 @@ bool32 AV_TryFrame(av_codec_info *AV, av_packet_info *AVLayer, int32 *err)
}
while (*err >= 0) {
- *err = avcodec_receive_frame(AV->VideoCodecContext, AVLayer->VideoFrame);
+ *err = avcodec_receive_frame(AV->VideoCodecContext, AV->VideoFrame);
if (*err == AVERROR_EOF) {
} else if (*err == AVERROR(EAGAIN)) {
*err = 0;
@@ -54,6 +54,8 @@ bool32 AV_TryFrame(av_codec_info *AV, av_packet_info *AVLayer, int32 *err)
return 0;
}
+// TODO(fox): Could be combined into AV_Init once we have dealloc functions for
+// the AVInfo allocation.
bool32 AV_IsFileSupported(char *filename)
{
int32 err = 0;
@@ -84,10 +86,10 @@ bool32 AV_IsFileSupported(char *filename)
return 1;
}
-void AV_CodecInfo_Init(char *filename, source *Source, memory *Memory)
+void AV_Init(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory)
{
- Source->Info.AVCodecInfo = AllocateMemory(Memory, sizeof(av_codec_info), P_AVInfo);
- av_codec_info *AV = (av_codec_info *)Source->Info.AVCodecInfo;
+ BitmapInfo->AVInfo = AllocateMemory(Memory, sizeof(av_info), P_AVInfo);
+ av_info *AV = (av_info *)BitmapInfo->AVInfo;
*AV = {};
int32 err = 0;
@@ -96,17 +98,20 @@ void AV_CodecInfo_Init(char *filename, source *Source, memory *Memory)
// while((type = av_hwdevice_iterate_types(type)) != AV_HWDEVICE_TYPE_NONE)
// printf("%s\n", av_hwdevice_get_type_name(type));
- AV->FileFormatContext = avformat_alloc_context();
- err = avformat_open_input(&AV->FileFormatContext, filename, NULL, NULL);;
+ // The two calls below theoretically shouldn't fail since we already tested them in IsFileSupported.
+ AV->FileFormatContext = avformat_alloc_context();
+ err = avformat_open_input(&AV->FileFormatContext, Source->Path, NULL, NULL);;
if (err < 0) {
fprintf(stderr, "Libav error: (%s)\n", av_err2str(err));
+ Assert(0);
}
err = avformat_find_stream_info(AV->FileFormatContext, NULL);
if (err < 0) {
fprintf(stderr, "Libav error: (%s)\n", av_err2str(err));
+ Assert(0);
}
for (int i = 0; i < AV->FileFormatContext->nb_streams; i++)
@@ -154,12 +159,20 @@ void AV_CodecInfo_Init(char *filename, source *Source, memory *Memory)
if (err < 0) {
fprintf(stderr, "Libav error: (%s)\n", av_err2str(err));
}
-
avcodec_open2(AV->VideoCodecContext, AV->VideoCodec, NULL);
if (err < 0) {
fprintf(stderr, "Libav error: (%s)\n", av_err2str(err));
}
+ AV->VideoPacket = av_packet_alloc();
+ if (err < 0) {
+ fprintf(stderr, "Libav error: (%s)\n", av_err2str(err));
+ }
+ AV->VideoFrame = av_frame_alloc();
+ if (err < 0) {
+ fprintf(stderr, "Libav error: (%s)\n", av_err2str(err));
+ }
+
Source->Info.FPS = (real32)AV->VideoStream->r_frame_rate.num / AV->VideoStream->r_frame_rate.den;
Source->Info.Width = AV->VideoCodecContext->width;
Source->Info.Height = AV->VideoCodecContext->height;
@@ -167,7 +180,7 @@ void AV_CodecInfo_Init(char *filename, source *Source, memory *Memory)
-void AV_GetPTSAverage(av_codec_info *AV, av_packet_info *AVLayer, int32 *err)
+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.
@@ -180,62 +193,34 @@ void AV_GetPTSAverage(av_codec_info *AV, av_packet_info *AVLayer, int32 *err)
int16 i = 0;
real32 AvgPTSPerSecond = 0;
for (;;) {
- if (AV_TryFrame(AV, AVLayer, err)) {
+ if (AV_TryFrame(AV, err)) {
if (i >= FPS * TestAmount) {
- AvgPTSPerSecond = (real32)AVLayer->VideoFrame->pts / TestAmount;
- printf("frame: %i, pts: %li\n", i, AVLayer->VideoFrame->pts);
+ AvgPTSPerSecond = (real32)AV->VideoFrame->pts / TestAmount;
+ printf("frame: %i, pts: %li\n", i, AV->VideoFrame->pts);
break;
}
i++;
- av_frame_unref(AVLayer->VideoFrame);
+ av_frame_unref(AV->VideoFrame);
}
}
- AV->AvgPTSPerFrame = (real32)AvgPTSPerSecond / (int32)(FPS + 0.5f);
- printf("Avg PTS per sec: %.06f, Avg PTS per frame: %.06f\n", AvgPTSPerSecond, AV->AvgPTSPerFrame);
+ Source->Info.AvgPTSPerFrame = (real32)AvgPTSPerSecond / (int32)(FPS + 0.5f);
+ printf("Avg PTS per sec: %.06f, Avg PTS per frame: %.06f\n", AvgPTSPerSecond, Source->Info.AvgPTSPerFrame);
av_seek_frame(AV->FileFormatContext, -1, 0, AVSEEK_FLAG_BACKWARD);
}
-
-void AV_PacketInfo_Init(layer_bitmap_info *BitmapInfo, memory *Memory)
-{
- BitmapInfo->AVPacketInfo = AllocateMemory(Memory, sizeof(av_packet_info), P_AVInfo);
- av_packet_info *AV = (av_packet_info *)BitmapInfo->AVPacketInfo;
- *AV = {};
- printf("%li", AV->PreviousPTS);
-
- int32 err = 0;
-
- AV->VideoPacket = av_packet_alloc();
- if (err < 0) {
- fprintf(stderr, "Libav error: (%s)\n", av_err2str(err));
- }
- AV->VideoFrame = av_frame_alloc();
- if (err < 0) {
- fprintf(stderr, "Libav error: (%s)\n", av_err2str(err));
- }
-}
-
-
-static void
-Convert4x4Chunk(pixel_buffer *Raster, uint8);
-static void
-ClearBuffer(pixel_buffer *Raster, void *);
-
bool32 AV_LoadVideoFrame(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, int32 TimelineFrame)
{
- av_codec_info *AV = (av_codec_info *)Source->Info.AVCodecInfo;
- av_packet_info *AVLayer = (av_packet_info *)BitmapInfo->AVPacketInfo;
-
+ av_info *AV = (av_info *)BitmapInfo->AVInfo;
int32 *CurrentlyRenderedFrame = &BitmapInfo->CurrentFrame;
int32 err = 0;
- if (!AV->AvgPTSPerFrame) {
- AV_GetPTSAverage(AV, AVLayer, &err);
+ if (!Source->Info.AvgPTSPerFrame) {
+ AV_GetPTSAverage(Source, AV, &err);
}
- Assert(AV->AvgPTSPerFrame);
+ Assert(Source->Info.AvgPTSPerFrame);
int p = 0;
int i = 0;
@@ -258,28 +243,28 @@ bool32 AV_LoadVideoFrame(source *Source, layer_bitmap_info *BitmapInfo, memory *
*CurrentlyRenderedFrame = FrameToSeek;
- int64 SeekPTS = (int64)(AV->AvgPTSPerFrame*FrameToSeek + 0.5f);
+ int64 SeekPTS = (int64)(Source->Info.AvgPTSPerFrame*FrameToSeek + 0.5f);
while (err >= 0) {
- if (AV_TryFrame(AV, AVLayer, &err)) {
+ if (AV_TryFrame(AV, &err)) {
// The first frame that gets loaded isn't always the actual
// first frame, so we need to check until it's correct.
- if (FrameToSeek == 0 && AVLayer->VideoFrame->pts != AV->VideoStream->start_time) {
- av_frame_unref(AVLayer->VideoFrame);
- printf("NON-START: avg: %li, real pts: %li", SeekPTS, AVLayer->VideoFrame->pts);
+ if (FrameToSeek == 0 && AV->VideoFrame->pts != AV->VideoStream->start_time) {
+ av_frame_unref(AV->VideoFrame);
+ printf("NON-START: avg: %li, real pts: %li", SeekPTS, AV->VideoFrame->pts);
continue;
}
- int64 Difference = AVLayer->VideoFrame->pts - SeekPTS;
- if (abs(Difference) < AV->AvgPTSPerFrame)
+ int64 Difference = AV->VideoFrame->pts - SeekPTS;
+ if (abs(Difference) < Source->Info.AvgPTSPerFrame)
{
- if (AVLayer->PreviousPTS == -1) {
- AVLayer->PreviousPTS = AVLayer->VideoFrame->pts;
- printf("avg: %li, real pts: %li, difference: %li\n", SeekPTS, AVLayer->VideoFrame->pts, Difference);
+ if (AV->PreviousPTS == -1) {
+ AV->PreviousPTS = AV->VideoFrame->pts;
+ printf("avg: %li, real pts: %li, difference: %li\n", SeekPTS, AV->VideoFrame->pts, Difference);
} else {
- printf("avg: %li, real pts: %li, difference: %li difference from last pts: %li\n", SeekPTS, AVLayer->VideoFrame->pts, AVLayer->VideoFrame->pts - SeekPTS, AVLayer->VideoFrame->pts - AVLayer->PreviousPTS);
- AVLayer->PreviousPTS = AVLayer->VideoFrame->pts;
+ printf("avg: %li, real pts: %li, difference: %li difference from last pts: %li\n", SeekPTS, AV->VideoFrame->pts, AV->VideoFrame->pts - SeekPTS, AV->VideoFrame->pts - AV->PreviousPTS);
+ AV->PreviousPTS = AV->VideoFrame->pts;
}
uint16 Width = Source->Info.Width;
@@ -287,31 +272,63 @@ bool32 AV_LoadVideoFrame(source *Source, layer_bitmap_info *BitmapInfo, memory *
uint16 BytesPerPixel = Source->Info.BytesPerPixel;
int32 Pitch = Width*BytesPerPixel;
- void *Buffer = AllocateMemory(Memory, Bitmap_CalcTotalBytes(Width, Height, BytesPerPixel), B_LoadedBitmaps);
+ // probably should rename this
+ memory_table *Table = &Memory->Slot[B_LoadedBitmaps];
+ uint64 Size = Bitmap_CalcTotalBytes(Width, Height, BytesPerPixel);
+ if (Table->CurrentPosition + Size > Table->Size) {
+ Table->CurrentPosition = 0;
+ Table->PointerIndex = 0;
+ }
+ cached_bitmap *Bitmap = &Memory->Bitmap[Table->PointerIndex];
+ if (Table->PointerIndex < Table->NumberOfPointers) {
+ bool32 Avail = false;
+ void *DataStart = Memory->Bitmap[Table->PointerIndex].Data;
+ while(!Avail) {
+ void *Data2 = Memory->Bitmap[Table->PointerIndex+1].Data;
+ uint64 BytesBetween = (uint8 *)Data2 - (uint8 *)DataStart;
+ if (BytesBetween < Size) {
+ Memory->Bitmap[Table->PointerIndex+1].SourceOwner = NULL;
+ Table->PointerIndex++;
+ } else {
+ Avail = true;
+ }
+ Table->NumberOfPointers--;
+ }
+ }
+ Table->NumberOfPointers++;
+ Bitmap->Data = AllocateMemory(Memory, Size, B_LoadedBitmaps);
+ if (!Bitmap->Data) {
+ Assert(0);
+ }
+ Bitmap->SourceOwner = Source;
+ Bitmap->Frame = FrameToSeek;
+ Bitmap->Index = Table->PointerIndex;
+ Table->PointerIndex++;
+ 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.
- AVLayer->RGBContext = sws_getContext(AVLayer->VideoFrame->width, AVLayer->VideoFrame->height, (AVPixelFormat)AVLayer->VideoFrame->format,
- AVLayer->VideoFrame->width, AVLayer->VideoFrame->height, AV_PIX_FMT_RGBA, SWS_BILINEAR,
+ 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(!AVLayer->RGBContext) {
+ if(!AV->RGBContext) {
printf("Libav error: SwsContext creation failed.");
}
- sws_scale(AVLayer->RGBContext, AVLayer->VideoFrame->data, AVLayer->VideoFrame->linesize, 0, AVLayer->VideoFrame->height,
+ sws_scale(AV->RGBContext, AV->VideoFrame->data, AV->VideoFrame->linesize, 0, AV->VideoFrame->height,
dst_data, out_linesize);
- av_frame_unref(AVLayer->VideoFrame);
+ av_frame_unref(AV->VideoFrame);
- if (!BitmapInfo->BitmapBuffer) {
- BitmapInfo->BitmapBuffer = AllocateMemory(Memory, Bitmap_CalcTotalBytes(Width, Height, BytesPerPixel), B_LayerBitmaps);
- }
+ Assert(BitmapInfo->BitmapBuffer);
void *DestBuffer = BitmapInfo->BitmapBuffer;
Bitmap_ConvertPacking(Buffer, DestBuffer, Width, Height, BytesPerPixel, 0);
+ // void *Buffer2 = AllocateMemory(Memory, Bitmap_CalcTotalBytes(Width, Height, BytesPerPixel), B_LoadedBitmaps);
+ // uint64 test = &Buffer2 - &Buffer;
// CopyToBuffer(Buffer, 1);
// Bitmap_Clear(Buffer, Source->Info.Width, Source->Info.Height, Source->Info.BytesPerPixel);
@@ -320,9 +337,9 @@ bool32 AV_LoadVideoFrame(source *Source, layer_bitmap_info *BitmapInfo, memory *
else
{
// If this gets printed when not seeking, a frame has been skipped!
- printf("FRAME SKIP: avg: %li, real pts: %li, difference: %li\n", SeekPTS, AVLayer->VideoFrame->pts, Difference);
+ printf("FRAME SKIP: avg: %li, real pts: %li, difference: %li\n", SeekPTS, AV->VideoFrame->pts, Difference);
}
- av_frame_unref(AVLayer->VideoFrame);
+ av_frame_unref(AV->VideoFrame);
}
}
/*