summaryrefslogtreecommitdiff
path: root/include/kitchensink
diff options
context:
space:
mode:
Diffstat (limited to 'include/kitchensink')
-rw-r--r--include/kitchensink/internal/audio/kitaudio.h11
-rw-r--r--include/kitchensink/internal/kitdecoder.h75
-rw-r--r--include/kitchensink/internal/kitlibstate.h8
-rw-r--r--include/kitchensink/internal/kitlist.h26
-rw-r--r--include/kitchensink/internal/libass.h66
-rw-r--r--include/kitchensink/internal/subtitle/kitatlas.h40
-rw-r--r--include/kitchensink/internal/subtitle/kitsubtitle.h17
-rw-r--r--include/kitchensink/internal/subtitle/kitsubtitlepacket.h22
-rw-r--r--include/kitchensink/internal/subtitle/renderers/kitsubass.h11
-rw-r--r--include/kitchensink/internal/subtitle/renderers/kitsubimage.h11
-rw-r--r--include/kitchensink/internal/subtitle/renderers/kitsubrenderer.h32
-rw-r--r--include/kitchensink/internal/utils/kitbuffer.h (renamed from include/kitchensink/internal/kitbuffer.h)2
-rw-r--r--include/kitchensink/internal/utils/kithelpers.h11
-rw-r--r--include/kitchensink/internal/utils/kitlog.h11
-rw-r--r--include/kitchensink/internal/utils/kitringbuffer.h (renamed from include/kitchensink/internal/kitringbuffer.h)3
-rw-r--r--include/kitchensink/internal/video/kitvideo.h13
-rw-r--r--include/kitchensink/kitchensink.h10
-rw-r--r--include/kitchensink/kitcodec.h32
-rw-r--r--include/kitchensink/kitconfig.h8
-rw-r--r--include/kitchensink/kiterror.h24
-rw-r--r--include/kitchensink/kitformat.h33
-rw-r--r--include/kitchensink/kitlib.h107
-rw-r--r--include/kitchensink/kitplayer.h393
-rw-r--r--include/kitchensink/kitsource.h212
-rw-r--r--include/kitchensink/kitutils.h28
25 files changed, 1068 insertions, 138 deletions
diff --git a/include/kitchensink/internal/audio/kitaudio.h b/include/kitchensink/internal/audio/kitaudio.h
new file mode 100644
index 0000000..e42770b
--- /dev/null
+++ b/include/kitchensink/internal/audio/kitaudio.h
@@ -0,0 +1,11 @@
+#ifndef KITAUDIO_H
+#define KITAUDIO_H
+
+#include "kitchensink/kitconfig.h"
+#include "kitchensink/kitsource.h"
+#include "kitchensink/internal/kitdecoder.h"
+
+KIT_LOCAL Kit_Decoder* Kit_CreateAudioDecoder(const Kit_Source *src, int stream_index);
+KIT_LOCAL int Kit_GetAudioDecoderData(Kit_Decoder *dec, unsigned char *buf, int len);
+
+#endif // KITAUDIO_H
diff --git a/include/kitchensink/internal/kitdecoder.h b/include/kitchensink/internal/kitdecoder.h
new file mode 100644
index 0000000..ef3edb7
--- /dev/null
+++ b/include/kitchensink/internal/kitdecoder.h
@@ -0,0 +1,75 @@
+#ifndef KITDECODER_H
+#define KITDECODER_H
+
+#include <stdbool.h>
+
+#include <SDL_mutex.h>
+#include <libavcodec/avcodec.h>
+#include <libavformat/avformat.h>
+
+#include "kitchensink/kitformat.h"
+#include "kitchensink/kitcodec.h"
+#include "kitchensink/kitconfig.h"
+#include "kitchensink/kitsource.h"
+#include "kitchensink/internal/utils/kitbuffer.h"
+
+enum {
+ KIT_DEC_BUF_IN = 0,
+ KIT_DEC_BUF_OUT,
+ KIT_DEC_BUF_COUNT
+};
+
+typedef struct Kit_Decoder Kit_Decoder;
+
+typedef void (*dec_decode_cb)(Kit_Decoder *dec, AVPacket *in_packet);
+typedef void (*dec_close_cb)(Kit_Decoder *dec);
+typedef void (*dec_free_packet_cb)(void *packet);
+
+KIT_LOCAL struct Kit_Decoder {
+ int stream_index; ///< Source stream index for the current stream
+ double clock_sync; ///< Sync source for current stream
+ double clock_pos; ///< Current pts for the stream
+ Kit_OutputFormat output; ///< Output format for the decoder
+
+ AVCodecContext *codec_ctx; ///< FFMpeg internal: Codec context
+ AVFormatContext *format_ctx; ///< FFMpeg internal: Format context (owner: Kit_Source)
+
+ SDL_mutex *output_lock; ///< Threading lock for output buffer
+ Kit_Buffer *buffer[2]; ///< Buffers for incoming and decoded packets
+
+ void *userdata; ///< Decoder specific information (Audio, video, subtitle context)
+ dec_decode_cb dec_decode; ///< Decoder decoding function callback
+ dec_close_cb dec_close; ///< Decoder close function callback
+};
+
+KIT_LOCAL Kit_Decoder* Kit_CreateDecoder(const Kit_Source *src, int stream_index,
+ int out_b_size, dec_free_packet_cb free_out_cb,
+ int thread_count);
+KIT_LOCAL void Kit_CloseDecoder(Kit_Decoder *dec);
+
+KIT_LOCAL int Kit_GetDecoderStreamIndex(const Kit_Decoder *dec);
+KIT_LOCAL int Kit_GetDecoderCodecInfo(const Kit_Decoder *dec, Kit_Codec *codec);
+KIT_LOCAL int Kit_GetDecoderOutputFormat(const Kit_Decoder *dec, Kit_OutputFormat *output);
+
+KIT_LOCAL void Kit_SetDecoderClockSync(Kit_Decoder *dec, double sync);
+KIT_LOCAL void Kit_ChangeDecoderClockSync(Kit_Decoder *dec, double sync);
+
+KIT_LOCAL int Kit_RunDecoder(Kit_Decoder *dec);
+KIT_LOCAL void Kit_ClearDecoderBuffers(Kit_Decoder *dec);
+
+KIT_LOCAL bool Kit_CanWriteDecoderInput(Kit_Decoder *dec);
+KIT_LOCAL int Kit_WriteDecoderInput(Kit_Decoder *dec, AVPacket *packet);
+KIT_LOCAL AVPacket* Kit_ReadDecoderInput(Kit_Decoder *dec);
+KIT_LOCAL void Kit_ClearDecoderInput(Kit_Decoder *dec);
+
+KIT_LOCAL int Kit_WriteDecoderOutput(Kit_Decoder *dec, void *packet);
+KIT_LOCAL void* Kit_PeekDecoderOutput(Kit_Decoder *dec);
+KIT_LOCAL void* Kit_ReadDecoderOutput(Kit_Decoder *dec);
+KIT_LOCAL void Kit_AdvanceDecoderOutput(Kit_Decoder *dec);
+KIT_LOCAL void Kit_ForEachDecoderOutput(Kit_Decoder *dec, Kit_ForEachItemCallback foreach_cb, void *userdata);
+KIT_LOCAL int Kit_LockDecoderOutput(Kit_Decoder *dec);
+KIT_LOCAL void Kit_UnlockDecoderOutput(Kit_Decoder *dec);
+KIT_LOCAL void Kit_ClearDecoderOutput(Kit_Decoder *dec);
+
+
+#endif // KITDECODER_H
diff --git a/include/kitchensink/internal/kitlibstate.h b/include/kitchensink/internal/kitlibstate.h
index e16a5c9..b92cebb 100644
--- a/include/kitchensink/internal/kitlibstate.h
+++ b/include/kitchensink/internal/kitlibstate.h
@@ -1,12 +1,18 @@
#ifndef KITLIBSTATE_H
#define KITLIBSTATE_H
-#include <ass/ass.h>
+#include "kitchensink/internal/libass.h"
#include "kitchensink/kitconfig.h"
typedef struct Kit_LibraryState {
unsigned int init_flags;
+ unsigned int thread_count;
+ unsigned int font_hinting;
+ unsigned int video_buf_frames;
+ unsigned int audio_buf_frames;
+ unsigned int subtitle_buf_frames;
ASS_Library *libass_handle;
+ void *ass_so_handle;
} Kit_LibraryState;
KIT_LOCAL Kit_LibraryState* Kit_GetLibraryState();
diff --git a/include/kitchensink/internal/kitlist.h b/include/kitchensink/internal/kitlist.h
deleted file mode 100644
index 85e3e3f..0000000
--- a/include/kitchensink/internal/kitlist.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef KITLIST_H
-#define KITLIST_H
-
-#include "kitchensink/kitconfig.h"
-
-typedef struct Kit_List Kit_List;
-
-typedef void (*Kit_ListFreeCallback)(void*);
-
-struct Kit_List {
- unsigned int size;
- unsigned int length;
- Kit_ListFreeCallback free_cb;
- void **data;
-};
-
-KIT_LOCAL Kit_List* Kit_CreateList(unsigned int size, Kit_ListFreeCallback free_cb);
-KIT_LOCAL void Kit_DestroyList(Kit_List *list);
-
-KIT_LOCAL void Kit_ClearList(Kit_List *list);
-KIT_LOCAL void Kit_RemoveFromList(Kit_List *list, unsigned int iterator);
-KIT_LOCAL void* Kit_IterateList(const Kit_List *list, unsigned int *iterator);
-KIT_LOCAL int Kit_WriteList(Kit_List *list, void *ptr);
-KIT_LOCAL int Kit_GetListLength(const Kit_List *list);
-
-#endif // KITLIST_H
diff --git a/include/kitchensink/internal/libass.h b/include/kitchensink/internal/libass.h
new file mode 100644
index 0000000..0f91d95
--- /dev/null
+++ b/include/kitchensink/internal/libass.h
@@ -0,0 +1,66 @@
+#ifndef KITLIBASS_H
+#define KITLIBASS_H
+
+#ifndef USE_DYNAMIC_LIBASS
+
+#include <ass/ass.h>
+
+#else // USE_DYNAMIC_LIBASS
+
+#include <stdint.h>
+#include <stdarg.h>
+
+#include "kitchensink/kitconfig.h"
+
+typedef struct ass_library ASS_Library;
+typedef struct ass_renderer ASS_Renderer;
+typedef struct ass_track ASS_Track;
+
+typedef struct ass_image {
+ int w, h;
+ int stride;
+ unsigned char *bitmap;
+ uint32_t color;
+ int dst_x, dst_y;
+ struct ass_image *next;
+ enum {
+ IMAGE_TYPE_CHARACTER,
+ IMAGE_TYPE_OUTLINE,
+ IMAGE_TYPE_SHADOW
+ } type;
+} ASS_Image;
+
+typedef enum {
+ ASS_HINTING_NONE = 0,
+ ASS_HINTING_LIGHT,
+ ASS_HINTING_NORMAL,
+ ASS_HINTING_NATIVE
+} ASS_Hinting;
+
+KIT_LOCAL ASS_Library* (*ass_library_init)(void);
+KIT_LOCAL void (*ass_library_done)(ASS_Library *priv);
+KIT_LOCAL void (*ass_process_codec_private)(ASS_Track *track, char *data, int size);
+KIT_LOCAL void (*ass_set_message_cb)(ASS_Library *priv, void (*msg_cb)(int level, const char *fmt, va_list args, void *data), void *data);
+KIT_LOCAL ASS_Renderer* (*ass_renderer_init)(ASS_Library *);
+KIT_LOCAL void (*ass_renderer_done)(ASS_Renderer *priv);
+KIT_LOCAL void (*ass_set_frame_size)(ASS_Renderer *priv, int w, int h);
+KIT_LOCAL void (*ass_set_hinting)(ASS_Renderer *priv, ASS_Hinting ht);
+KIT_LOCAL void (*ass_set_fonts)(ASS_Renderer *priv, const char *default_font, const char *default_family, int dfp, const char *config, int update);
+KIT_LOCAL ASS_Image* (*ass_render_frame)(ASS_Renderer *priv, ASS_Track *track, long long now, int *detect_change);
+KIT_LOCAL ASS_Track* (*ass_new_track)(ASS_Library *);
+KIT_LOCAL void (*ass_free_track)(ASS_Track *track);
+KIT_LOCAL void (*ass_process_data)(ASS_Track *track, char *data, int size);
+KIT_LOCAL void (*ass_process_chunk)(ASS_Track *track, char *data, int size, long long timecode, long long duration);
+KIT_LOCAL void (*ass_add_font)(ASS_Library *library, char *name, char *data, int data_size);
+KIT_LOCAL void (*ass_set_storage_size)(ASS_Renderer *priv, int w, int h);
+
+KIT_LOCAL int load_libass(void *handle);
+
+#endif // USE_DYNAMIC_LIBASS
+
+// For compatibility
+#ifndef ASS_FONTPROVIDER_AUTODETECT
+#define ASS_FONTPROVIDER_AUTODETECT 1
+#endif
+
+#endif // KITLIBASS_H
diff --git a/include/kitchensink/internal/subtitle/kitatlas.h b/include/kitchensink/internal/subtitle/kitatlas.h
new file mode 100644
index 0000000..d9207c1
--- /dev/null
+++ b/include/kitchensink/internal/subtitle/kitatlas.h
@@ -0,0 +1,40 @@
+#ifndef KITATLAS_H
+#define KITATLAS_H
+
+#include <stdbool.h>
+#include <SDL_rect.h>
+#include <SDL_render.h>
+
+#include "kitchensink/kitconfig.h"
+
+typedef struct Kit_TextureAtlasItem {
+ int cur_shelf; //< Current shelf number in cache
+ int cur_slot; //< Current slot on shelf in cache
+ SDL_Rect source; //< Source coordinates on cache surface
+ SDL_Rect target; //< Target coordinates on output surface
+} Kit_TextureAtlasItem;
+
+typedef struct Kit_Shelf {
+ uint16_t width;
+ uint16_t height;
+ uint16_t count;
+} Kit_Shelf;
+
+typedef struct Kit_TextureAtlas {
+ int cur_items; //< Current items count
+ int max_items; //< Maximum items count
+ int max_shelves; //< Maximum shelf count
+ int w; //< Current atlas width
+ int h; //< Current atlas height
+ Kit_TextureAtlasItem *items; //< Cached items
+ Kit_Shelf *shelves; //< Atlas shelves
+} Kit_TextureAtlas;
+
+KIT_LOCAL Kit_TextureAtlas* Kit_CreateAtlas();
+KIT_LOCAL void Kit_FreeAtlas(Kit_TextureAtlas *atlas);
+KIT_LOCAL void Kit_ClearAtlasContent(Kit_TextureAtlas *atlas);
+KIT_LOCAL void Kit_CheckAtlasTextureSize(Kit_TextureAtlas *atlas, SDL_Texture *texture);
+KIT_LOCAL int Kit_GetAtlasItems(const Kit_TextureAtlas *atlas, SDL_Rect *sources, SDL_Rect *targets, int limit);
+KIT_LOCAL int Kit_AddAtlasItem(Kit_TextureAtlas *atlas, SDL_Texture *texture, SDL_Surface *surface, const SDL_Rect *target);
+
+#endif // KITATLAS_H
diff --git a/include/kitchensink/internal/subtitle/kitsubtitle.h b/include/kitchensink/internal/subtitle/kitsubtitle.h
new file mode 100644
index 0000000..8bb2a62
--- /dev/null
+++ b/include/kitchensink/internal/subtitle/kitsubtitle.h
@@ -0,0 +1,17 @@
+#ifndef KITSUBTITLE_H
+#define KITSUBTITLE_H
+
+#include <SDL_render.h>
+
+#include "kitchensink/kitconfig.h"
+#include "kitchensink/kitsource.h"
+#include "kitchensink/internal/kitdecoder.h"
+
+KIT_LOCAL Kit_Decoder* Kit_CreateSubtitleDecoder(
+ const Kit_Source *src, int stream_index, int video_w, int video_h, int screen_w, int screen_h);
+KIT_LOCAL void Kit_GetSubtitleDecoderTexture(Kit_Decoder *dec, SDL_Texture *texture);
+KIT_LOCAL void Kit_SetSubtitleDecoderSize(Kit_Decoder *dec, int w, int h);
+KIT_LOCAL int Kit_GetSubtitleDecoderInfo(
+ Kit_Decoder *dec, SDL_Texture *texture, SDL_Rect *sources, SDL_Rect *targets, int limit);
+
+#endif // KITSUBTITLE_H
diff --git a/include/kitchensink/internal/subtitle/kitsubtitlepacket.h b/include/kitchensink/internal/subtitle/kitsubtitlepacket.h
new file mode 100644
index 0000000..c560c74
--- /dev/null
+++ b/include/kitchensink/internal/subtitle/kitsubtitlepacket.h
@@ -0,0 +1,22 @@
+#ifndef KITSUBTITLEPACKET_H
+#define KITSUBTITLEPACKET_H
+
+#include <stdbool.h>
+#include <SDL_surface.h>
+
+#include "kitchensink/kitconfig.h"
+
+typedef struct Kit_SubtitlePacket {
+ double pts_start;
+ double pts_end;
+ int x;
+ int y;
+ bool clear;
+ SDL_Surface *surface;
+} Kit_SubtitlePacket;
+
+KIT_LOCAL Kit_SubtitlePacket* Kit_CreateSubtitlePacket(
+ bool clear, double pts_start, double pts_end, int pos_x, int pos_y, SDL_Surface *surface);
+KIT_LOCAL void Kit_FreeSubtitlePacket(Kit_SubtitlePacket *packet);
+
+#endif // KITSUBTITLEPACKET_H
diff --git a/include/kitchensink/internal/subtitle/renderers/kitsubass.h b/include/kitchensink/internal/subtitle/renderers/kitsubass.h
new file mode 100644
index 0000000..6dff50c
--- /dev/null
+++ b/include/kitchensink/internal/subtitle/renderers/kitsubass.h
@@ -0,0 +1,11 @@
+#ifndef KITSUBASS_H
+#define KITSUBASS_H
+
+#include "kitchensink/kitconfig.h"
+#include "kitchensink/internal/kitdecoder.h"
+#include "kitchensink/internal/subtitle/renderers/kitsubrenderer.h"
+
+KIT_LOCAL Kit_SubtitleRenderer* Kit_CreateASSSubtitleRenderer(
+ Kit_Decoder *dec, int video_w, int video_h, int screen_w, int screen_h);
+
+#endif // KITSUBASS_H
diff --git a/include/kitchensink/internal/subtitle/renderers/kitsubimage.h b/include/kitchensink/internal/subtitle/renderers/kitsubimage.h
new file mode 100644
index 0000000..883fde3
--- /dev/null
+++ b/include/kitchensink/internal/subtitle/renderers/kitsubimage.h
@@ -0,0 +1,11 @@
+#ifndef KITSUBIMAGE_H
+#define KITSUBIMAGE_H
+
+#include "kitchensink/kitconfig.h"
+#include "kitchensink/internal/kitdecoder.h"
+#include "kitchensink/internal/subtitle/renderers/kitsubrenderer.h"
+
+KIT_LOCAL Kit_SubtitleRenderer* Kit_CreateImageSubtitleRenderer(
+ Kit_Decoder *dec, int video_w, int video_h, int screen_w, int screen_h);
+
+#endif // KITSUBIMAGE_H
diff --git a/include/kitchensink/internal/subtitle/renderers/kitsubrenderer.h b/include/kitchensink/internal/subtitle/renderers/kitsubrenderer.h
new file mode 100644
index 0000000..3c37b00
--- /dev/null
+++ b/include/kitchensink/internal/subtitle/renderers/kitsubrenderer.h
@@ -0,0 +1,32 @@
+#ifndef KITSUBRENDERER_H
+#define KITSUBRENDERER_H
+
+#include <SDL_render.h>
+
+#include "kitchensink/kitsource.h"
+
+typedef struct Kit_SubtitleRenderer Kit_SubtitleRenderer;
+typedef struct Kit_TextureAtlas Kit_TextureAtlas;
+typedef struct Kit_Decoder Kit_Decoder;
+
+typedef void (*ren_render_cb)(Kit_SubtitleRenderer *ren, void *src, double start_pts, double end_pts);
+typedef int (*ren_get_data_cb)(Kit_SubtitleRenderer *ren, Kit_TextureAtlas *atlas, SDL_Texture *texture, double current_pts);
+typedef void (*ren_set_size_cb)(Kit_SubtitleRenderer *ren, int w, int h);
+typedef void (*ren_close_cb)(Kit_SubtitleRenderer *ren);
+
+struct Kit_SubtitleRenderer {
+ Kit_Decoder *dec;
+ void *userdata;
+ ren_render_cb ren_render; ///< Subtitle rendering function callback
+ ren_get_data_cb ren_get_data; ///< Subtitle data getter function callback
+ ren_set_size_cb ren_set_size; ///< Screen size setter function callback
+ ren_close_cb ren_close; ///< Subtitle renderer close function callback
+};
+
+KIT_LOCAL Kit_SubtitleRenderer* Kit_CreateSubtitleRenderer(Kit_Decoder *dec);
+KIT_LOCAL void Kit_RunSubtitleRenderer(Kit_SubtitleRenderer *ren, void *src, double start_pts, double end_pts);
+KIT_LOCAL int Kit_GetSubtitleRendererData(Kit_SubtitleRenderer *ren, Kit_TextureAtlas *atlas, SDL_Texture *texture, double current_pts);
+KIT_LOCAL void Kit_SetSubtitleRendererSize(Kit_SubtitleRenderer *ren, int w, int h);
+KIT_LOCAL void Kit_CloseSubtitleRenderer(Kit_SubtitleRenderer *ren);
+
+#endif // KITSUBRENDERER_H
diff --git a/include/kitchensink/internal/kitbuffer.h b/include/kitchensink/internal/utils/kitbuffer.h
index 4d0f8cc..67d93c3 100644
--- a/include/kitchensink/internal/kitbuffer.h
+++ b/include/kitchensink/internal/utils/kitbuffer.h
@@ -6,6 +6,7 @@
typedef struct Kit_Buffer Kit_Buffer;
typedef void (*Kit_BufferFreeCallback)(void*);
+typedef void (*Kit_ForEachItemCallback)(void*, void *userdata);
struct Kit_Buffer {
unsigned int read_p;
@@ -23,6 +24,7 @@ KIT_LOCAL void* Kit_ReadBuffer(Kit_Buffer *buffer);
KIT_LOCAL void* Kit_PeekBuffer(const Kit_Buffer *buffer);
KIT_LOCAL void Kit_AdvanceBuffer(Kit_Buffer *buffer);
KIT_LOCAL int Kit_WriteBuffer(Kit_Buffer *buffer, void *ptr);
+KIT_LOCAL void Kit_ForEachItemInBuffer(const Kit_Buffer *buffer, Kit_ForEachItemCallback cb, void *userdata);
KIT_LOCAL int Kit_IsBufferFull(const Kit_Buffer *buffer);
#endif // KITBUFFER_H
diff --git a/include/kitchensink/internal/utils/kithelpers.h b/include/kitchensink/internal/utils/kithelpers.h
new file mode 100644
index 0000000..5b94a7a
--- /dev/null
+++ b/include/kitchensink/internal/utils/kithelpers.h
@@ -0,0 +1,11 @@
+#ifndef KITHELPERS_H
+#define KITHELPERS_H
+
+#include <stdbool.h>
+#include <libavformat/avformat.h>
+#include "kitchensink/kitconfig.h"
+
+KIT_LOCAL double _GetSystemTime();
+KIT_LOCAL bool attachment_is_font(AVStream *stream);
+
+#endif // KITHELPERS_H
diff --git a/include/kitchensink/internal/utils/kitlog.h b/include/kitchensink/internal/utils/kitlog.h
new file mode 100644
index 0000000..d298592
--- /dev/null
+++ b/include/kitchensink/internal/utils/kitlog.h
@@ -0,0 +1,11 @@
+#ifndef KITLOG_H
+#define KITLOG_H
+
+#ifdef NDEBUG
+#define LOG(...)
+#else
+#include <stdio.h>
+#define LOG(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)
+#endif
+
+#endif // KITLOG_H
diff --git a/include/kitchensink/internal/kitringbuffer.h b/include/kitchensink/internal/utils/kitringbuffer.h
index 2f67520..153dfd4 100644
--- a/include/kitchensink/internal/kitringbuffer.h
+++ b/include/kitchensink/internal/utils/kitringbuffer.h
@@ -6,7 +6,8 @@
typedef struct Kit_RingBuffer {
int size;
int len;
- int wpos, rpos;
+ int wpos;
+ int rpos;
char* data;
} Kit_RingBuffer;
diff --git a/include/kitchensink/internal/video/kitvideo.h b/include/kitchensink/internal/video/kitvideo.h
new file mode 100644
index 0000000..5c072ef
--- /dev/null
+++ b/include/kitchensink/internal/video/kitvideo.h
@@ -0,0 +1,13 @@
+#ifndef KITVIDEO_H
+#define KITVIDEO_H
+
+#include <SDL_render.h>
+
+#include "kitchensink/kitconfig.h"
+#include "kitchensink/kitsource.h"
+#include "kitchensink/internal/kitdecoder.h"
+
+KIT_LOCAL Kit_Decoder* Kit_CreateVideoDecoder(const Kit_Source *src, int stream_index);
+KIT_LOCAL int Kit_GetVideoDecoderData(Kit_Decoder *dec, SDL_Texture *texture);
+
+#endif // KITVIDEO_H
diff --git a/include/kitchensink/kitchensink.h b/include/kitchensink/kitchensink.h
index be318a5..7fc08e6 100644
--- a/include/kitchensink/kitchensink.h
+++ b/include/kitchensink/kitchensink.h
@@ -1,8 +1,18 @@
#ifndef KITCHENSINK_H
#define KITCHENSINK_H
+/**
+ * @brief Header aggregator
+ *
+ * @file kitchensink.h
+ * @author Tuomas Virtanen
+ * @date 2018-06-27
+ */
+
#include "kitchensink/kitlib.h"
#include "kitchensink/kiterror.h"
+#include "kitchensink/kitformat.h"
+#include "kitchensink/kitcodec.h"
#include "kitchensink/kitsource.h"
#include "kitchensink/kitplayer.h"
#include "kitchensink/kitutils.h"
diff --git a/include/kitchensink/kitcodec.h b/include/kitchensink/kitcodec.h
new file mode 100644
index 0000000..589f84d
--- /dev/null
+++ b/include/kitchensink/kitcodec.h
@@ -0,0 +1,32 @@
+#ifndef KITCODEC_H
+#define KITCODEC_H
+
+/**
+ * @brief Codec type
+ *
+ * @file kitcodec.h
+ * @author Tuomas Virtanen
+ * @date 2018-06-25
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define KIT_CODEC_NAME_MAX 8
+#define KIT_CODEC_DESC_MAX 48
+
+/**
+ * @brief Contains information about the used codec for playback
+ */
+typedef struct Kit_Codec {
+ unsigned int threads; ///< Currently enabled threads (For all decoders)
+ char name[KIT_CODEC_NAME_MAX]; ///< Codec short name, eg. "ogg" or "webm"
+ char description[KIT_CODEC_DESC_MAX]; ///< Codec longer, more descriptive name
+} Kit_Codec;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // KITCODEC_H
diff --git a/include/kitchensink/kitconfig.h b/include/kitchensink/kitconfig.h
index e8b2d01..8eda779 100644
--- a/include/kitchensink/kitconfig.h
+++ b/include/kitchensink/kitconfig.h
@@ -1,6 +1,14 @@
#ifndef KITCONFIG_H
#define KITCONFIG_H
+/**
+ * @brief Public API configurations
+ *
+ * @file kitconfig.h
+ * @author Tuomas Virtanen
+ * @date 2018-06-25
+ */
+
#if defined _WIN32 || defined __CYGWIN__
#define KIT_DLL_IMPORT __declspec(dllimport)
#define KIT_DLL_EXPORT __declspec(dllexport)
diff --git a/include/kitchensink/kiterror.h b/include/kitchensink/kiterror.h
index 824ea8c..e6c2acd 100644
--- a/include/kitchensink/kiterror.h
+++ b/include/kitchensink/kiterror.h
@@ -1,14 +1,38 @@
#ifndef KITERROR_H
#define KITERROR_H
+/**
+ * @brief Error handling functions
+ *
+ * @file kiterror.h
+ * @author Tuomas Virtanen
+ * @date 2018-06-25
+ */
+
#include "kitchensink/kitconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
+/**
+ * @brief Returns the latest error. This is set by SDL_kitchensink library functions on error.
+ *
+ * @return Error message or NULL
+ */
KIT_API const char* Kit_GetError();
+
+/**
+ * @brief Sets the error message. This should really only be used by the library.
+ *
+ * @param fmt Message format
+ * @param ... Message arguments
+ */
KIT_API void Kit_SetError(const char* fmt, ...);
+
+/**
+ * @brief Clears latest error message. After this, Kit_GetError() will return NULL.
+ */
KIT_API void Kit_ClearError();
#ifdef __cplusplus
diff --git a/include/kitchensink/kitformat.h b/include/kitchensink/kitformat.h
new file mode 100644
index 0000000..3e8df91
--- /dev/null
+++ b/include/kitchensink/kitformat.h
@@ -0,0 +1,33 @@
+#ifndef KITFORMAT_H
+#define KITFORMAT_H
+
+/**
+ * @brief Audio/video output format type
+ *
+ * @file kitformat.h
+ * @author Tuomas Virtanen
+ * @date 2018-06-25
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Contains information about the data format coming out from the player
+ */
+typedef struct Kit_OutputFormat {
+ unsigned int format; ///< SDL Format (SDL_PixelFormat if video/subtitle, SDL_AudioFormat if audio)
+ int is_signed; ///< Signedness, 1 = signed, 0 = unsigned (if audio)
+ int bytes; ///< Bytes per sample per channel (if audio)
+ int samplerate; ///< Sampling rate (if audio)
+ int channels; ///< Channels (if audio)
+ int width; ///< Width in pixels (if video)
+ int height; ///< Height in pixels (if video)
+} Kit_OutputFormat;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // KITFORMAT_H
diff --git a/include/kitchensink/kitlib.h b/include/kitchensink/kitlib.h
index 9a827be..a5fe913 100644
--- a/include/kitchensink/kitlib.h
+++ b/include/kitchensink/kitlib.h
@@ -1,29 +1,118 @@
#ifndef KITLIB_H
#define KITLIB_H
-#include "kitchensink/kiterror.h"
-#include "kitchensink/kitsource.h"
-#include "kitchensink/kitplayer.h"
-#include "kitchensink/kitutils.h"
+/**
+ * @brief Library initialization and deinitialization functionality
+ *
+ * @file kitlib.h
+ * @author Tuomas Virtanen
+ * @date 2018-06-25
+ */
+
#include "kitchensink/kitconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
+/**
+ * @brief Font hinting options. Used as values for Kit_SetHint(KIT_HINT_FONT_HINTING, ...).
+ */
+enum {
+ KIT_FONT_HINTING_NONE = 0, ///< No hinting. This is recommended option
+ KIT_FONT_HINTING_LIGHT, ///< Light hinting. Use this if you need hinting
+ KIT_FONT_HINTING_NORMAL, ///< Not recommended, please see libass docs for details
+ KIT_FONT_HINTING_NATIVE, ///< Not recommended, please see libass docs for details
+ KIT_FONT_HINTING_COUNT
+};
+
+/**
+ * @brief SDL_kitchensink library version container
+ */
typedef struct Kit_Version {
- unsigned char major;
- unsigned char minor;
- unsigned char patch;
+ unsigned char major; ///< Major version number, raising this signifies API breakage
+ unsigned char minor; ///< Minor version number, small/internal changes
+ unsigned char patch; ///< Patch version number, bugfixes etc.
} Kit_Version;
+/**
+ * @brief Library hint types. Used as keys for Kit_SetHint().
+ *
+ * Note that all of these must be set *before* player initialization for them to take effect!
+ */
+typedef enum Kit_HintType {
+ KIT_HINT_FONT_HINTING, ///< Set font hinting mode (currently used for libass)
+ KIT_HINT_THREAD_COUNT, ///< Set thread count for ffmpeg (1 by default)
+ KIT_HINT_VIDEO_BUFFER_FRAMES, ///< Video output buffer frames (3 by default)
+ KIT_HINT_AUDIO_BUFFER_FRAMES, ///< Audio output buffers (64 by default)
+ KIT_HINT_SUBTITLE_BUFFER_FRAMES ///< Subtitle output buffers (64 by default, used by image subtitles)
+} Kit_HintType;
+
+/**
+ * @brief Library initialization options, please see Kit_Init()
+ *
+ */
enum {
- KIT_INIT_FORMATS = 0x1,
- KIT_INIT_NETWORK = 0x2,
+ KIT_INIT_NETWORK = 0x1, ///< Initialise ffmpeg network support
+ KIT_INIT_ASS = 0x2 ///< Initialize libass support (library must be linked statically or loadable dynamically)
};
+/**
+ * @brief Initialize SDL_kitchensink library.
+ *
+ * This MUST be run before doing anything. After you are done using the library, you should use Kit_Quit() to
+ * deinitialize everything. Otherwise there might be resource leaks.
+ *
+ * Following flags can be used to initialize subsystems:
+ * - `KIT_INIT_NETWORK` for ffmpeg network support (playback from the internet, for example)
+ * - `KIT_INIT_ASS` for libass subtitles (text and ass/ssa subtitle support)
+ *
+ * Note that if this function fails, the failure reason should be available via Kit_GetError().
+ *
+ * For example:
+ * ```
+ * if(Kit_Init(KIT_INIT_NETWORK|KIT_INIT_ASS) != 0) {
+ * fprintf(stderr, "Error: %s\n", Kit_GetError());
+ * return 1;
+ * }
+ * ```
+ *
+ * @param flags Library initialization flags
+ * @return Returns 0 on success, 1 on failure.
+ */
KIT_API int Kit_Init(unsigned int flags);
+
+/**
+ * @brief Deinitializes SDL_kitchensink
+ *
+ * Note that any calls to library functions after this will cause undefined behaviour!
+ */
KIT_API void Kit_Quit();
+
+/**
+ * @brief Sets a librarywide hint
+ *
+ * This can be used to set hints on how the library should behave. See Kit_HintType
+ * for all the options.
+ *
+ * @param type Hint type (refer to Kit_HintType for options)
+ * @param value Value for the hint
+ */
+KIT_API void Kit_SetHint(Kit_HintType type, int value);
+
+/**
+ * @brief Gets a previously set or default hint value
+ *
+ * @param type Hint type (refer to Kit_HintType for options)
+ * @return Hint value
+ */
+KIT_API int Kit_GetHint(Kit_HintType type);
+
+/**
+ * @brief Can be used to fetch the version of the linked SDL_kitchensink library
+ *
+ * @param version Allocated Kit_Version
+ */
KIT_API void Kit_GetVersion(Kit_Version *version);
#ifdef __cplusplus
diff --git a/include/kitchensink/kitplayer.h b/include/kitchensink/kitplayer.h
index b9ea1c7..1c73020 100644
--- a/include/kitchensink/kitplayer.h
+++ b/include/kitchensink/kitplayer.h
@@ -1,124 +1,339 @@
#ifndef KITPLAYER_H
#define KITPLAYER_H
+/**
+ * @brief Video/audio player functions
+ *
+ * @file kitplayer.h
+ * @author Tuomas Virtanen
+ * @date 2018-06-27
+ */
+
#include "kitchensink/kitsource.h"
#include "kitchensink/kitconfig.h"
+#include "kitchensink/kitformat.h"
+#include "kitchensink/kitcodec.h"
-#include <SDL2/SDL_render.h>
-#include <SDL2/SDL_thread.h>
-#include <SDL2/SDL_surface.h>
-
-#include <stdbool.h>
+#include <SDL_render.h>
#ifdef __cplusplus
extern "C" {
#endif
-#define KIT_CODECMAX 16
-#define KIT_CODECNAMEMAX 128
-
+/**
+ * @brief Playback states
+ */
typedef enum Kit_PlayerState {
KIT_STOPPED = 0, ///< Playback stopped or has not started yet.
- KIT_PLAYING, ///< Playback started & player is actively decoding.
- KIT_PAUSED, ///< Playback paused; player is actively decoding but no new data is given out.
- KIT_CLOSED ///< Playback is stopped and player is closing.
+ KIT_PLAYING, ///< Playback started & player is actively decoding.
+ KIT_PAUSED, ///< Playback paused; player is actively decoding but no new data is given out.
+ KIT_CLOSED, ///< Playback is stopped and player is closing.
} Kit_PlayerState;
-typedef struct Kit_AudioFormat {
- int stream_idx; ///< Stream index
- bool is_enabled; ///< Is stream enabled
- unsigned int format; ///< SDL Audio Format
- bool is_signed; ///< Signedness
- int bytes; ///< Bytes per sample per channel
- int samplerate; ///< Sampling rate
- int channels; ///< Channels
-} Kit_AudioFormat;
-
-typedef struct Kit_VideoFormat {
- int stream_idx; ///< Stream index
- bool is_enabled; ///< Is stream enabled
- unsigned int format; ///< SDL Pixel Format
- int width; ///< Width in pixels
- int height; ///< Height in pixels
-} Kit_VideoFormat;
-
-typedef struct Kit_SubtitleFormat {
- int stream_idx; ///< Stream index
- bool is_enabled; ///< Is stream enabled
-} Kit_SubtitleFormat;
-
+/**
+ * @brief Player state container
+ */
typedef struct Kit_Player {
- // Local state
- Kit_PlayerState state; ///< Playback state
- Kit_VideoFormat vformat; ///< Video format information
- Kit_AudioFormat aformat; ///< Audio format information
- Kit_SubtitleFormat sformat; ///< Subtitle format information
-
- // Synchronization
- double clock_sync; ///< Clock sync point
- double pause_start; ///< Timestamp of pause beginning
- double vclock_pos; ///< Video stream last pts
-
- // Threading
- SDL_Thread *dec_thread; ///< Decoder thread
- SDL_mutex *vmutex; ///< Video stream buffer lock
- SDL_mutex *amutex; ///< Audio stream buffer lock
- SDL_mutex *smutex; ///< Subtitle stream buffer lock
- SDL_mutex *cmutex; ///< Control stream buffer lock
-
- // Buffers
- void *abuffer; ///< Audio stream buffer
- void *vbuffer; ///< Video stream buffer
- void *sbuffer; ///< Subtitle stream buffer
- void *cbuffer; ///< Control stream buffer
-
- // FFmpeg internal state
- void *vcodec_ctx; ///< FFmpeg: Video codec context
- void *acodec_ctx; ///< FFmpeg: Audio codec context
- void *scodec_ctx; ///< FFmpeg: Subtitle codec context
- void *tmp_vframe; ///< FFmpeg: Preallocated temporary video frame
- void *tmp_aframe; ///< FFmpeg: Preallocated temporary audio frame
- void *tmp_sframe; ///< FFmpeg: Preallocated temporary subtitle frame
- void *swr; ///< FFmpeg: Audio resampler
- void *sws; ///< FFmpeg: Video converter
-
- // libass
- void *ass_renderer;
- void *ass_track;
-
- // Other
- uint8_t seek_flag;
- const Kit_Source *src; ///< Reference to Audio/Video source
+ Kit_PlayerState state; ///< Playback state
+ void *decoders[3]; ///< Decoder contexts
+ void *dec_thread; ///< Decoder thread
+ void *dec_lock; ///< Decoder lock
+ const Kit_Source *src; ///< Reference to Audio/Video source
+ double pause_started; ///< Temporary flag for handling pauses
} Kit_Player;
+/**
+ * @brief Contains data about a stream selected for playback
+ */
+typedef struct Kit_PlayerStreamInfo {
+ Kit_Codec codec; ///< Decoder codec information
+ Kit_OutputFormat output; ///< Information about the output format
+} Kit_PlayerStreamInfo;
+
+/**
+ * @brief Contains information about the streams selected for playback
+ *
+ */
typedef struct Kit_PlayerInfo {
- char acodec[KIT_CODECMAX]; ///< Audio codec short name, eg "ogg", "mp3"
- char acodec_name[KIT_CODECNAMEMAX]; ///< Audio codec long, more descriptive name
- char vcodec[KIT_CODECMAX]; ///< Video codec short name, eg. "x264"
- char vcodec_name[KIT_CODECNAMEMAX]; ///< Video codec long, more descriptive name
- char scodec[KIT_CODECMAX]; ///< Subtitle codec short name, eg. "ass"
- char scodec_name[KIT_CODECNAMEMAX]; ///< Subtitle codec long, more descriptive name
- Kit_VideoFormat video; ///< Video format information
- Kit_AudioFormat audio; ///< Audio format information
- Kit_SubtitleFormat subtitle; ///< Subtitle format information
+ Kit_PlayerStreamInfo video; ///< Video stream data
+ Kit_PlayerStreamInfo audio; ///< Audio stream data
+ Kit_PlayerStreamInfo subtitle; ///< Subtitle stream data
} Kit_PlayerInfo;
-KIT_API Kit_Player* Kit_CreatePlayer(const Kit_Source *src);
+/**
+ * @brief Creates a new player from a source.
+ *
+ * Creates a new player from the given source. The source must be previously succesfully
+ * initialized by calling either Kit_CreateSourceFromUrl() or Kit_CreateSourceFromCustom(),
+ * and it must not be used by any other player. Source must stay valid during the whole
+ * playback (as in, don't close it while stuff is playing).
+ *
+ * Screen width and height are used for subtitle positioning, scaling and rendering resolution.
+ * Ideally this should be precisely the size of your screen surface (in pixels).
+ * Higher resolution leads to higher resolution text rendering. This MUST be set precisely
+ * if you plan to use font hinting! If you don't care or don't have subtitles at all,
+ * set both to video surface size or 0.
+ *
+ * For streams, either video and/or audio stream MUST be set! Either set the stream indexes manually,
+ * or pick them automatically by using Kit_GetBestSourceStream().
+ *
+ * On success, this will return an initialized Kit_Player which can later be freed by Kit_ClosePlayer().
+ * On error, NULL is returned and a more detailed error is availably via Kit_GetError().
+ *
+ * For example:
+ * ```
+ * Kit_Player *player = Kit_CreatePlayer(
+ * src,
+ * Kit_GetBestSourceStream(src, KIT_STREAMTYPE_VIDEO),
+ * Kit_GetBestSourceStream(src, KIT_STREAMTYPE_AUDIO),
+ * Kit_GetBestSourceStream(src, KIT_STREAMTYPE_SUBTITLE),
+ * 1280, 720);
+ * if(player == NULL) {
+ * fprintf(stderr, "Unable to create player: %s\n", Kit_GetError());
+ * return 1;
+ * }
+ * ```
+ *
+ * @param src Valid video/audio source
+ * @param video_stream_index Video stream index or -1 if not wanted
+ * @param audio_stream_index Audio stream index or -1 if not wanted
+ * @param subtitle_stream_index Subtitle stream index or -1 if not wanted
+ * @param screen_w Screen width in pixels
+ * @param screen_h Screen height in pixels
+ * @return Ínitialized Kit_Player or NULL
+ */
+KIT_API Kit_Player* Kit_CreatePlayer(const Kit_Source *src,
+ int video_stream_index,
+ int audio_stream_index,
+ int subtitle_stream_index,
+ int screen_w,
+ int screen_h);
+
+/**
+ * @brief Close previously initialized player
+ *
+ * Closes a previously initialized Kit_Player instance. Note that this does NOT free
+ * the linked Kit_Source -- you must free it manually.
+ *
+ * @param player Player instance
+ */
KIT_API void Kit_ClosePlayer(Kit_Player *player);
-KIT_API int Kit_UpdatePlayer(Kit_Player *player);
-KIT_API int Kit_GetVideoData(Kit_Player *player, SDL_Texture *texture);
-KIT_API int Kit_GetSubtitleData(Kit_Player *player, SDL_Renderer *renderer);
-KIT_API int Kit_GetAudioData(Kit_Player *player, unsigned char *buffer, int length, int cur_buf_len);
+/**
+ * @brief Sets the current screen size in pixels
+ *
+ * Call this to change the subtitle font rendering resolution if eg. your
+ * video window size changes.
+ *
+ * This does nothing if subtitles are not in use or if subtitles are bitmaps.
+ *
+ * @param player Player instance
+ * @param w New width in pixels
+ * @param h New height in pixels
+ */
+KIT_API void Kit_SetPlayerScreenSize(Kit_Player *player, int w, int h);
+
+/**
+ * @brief Gets the current video stream index
+ *
+ * Returns the current video stream index or -1 if one is not selected.
+ *
+ * @param player Player instance
+ * @return Video stream index or -1
+ */
+KIT_API int Kit_GetPlayerVideoStream(const Kit_Player *player);
+
+/**
+ * @brief Gets the current audio stream index
+ *
+ * Returns the current audio stream index or -1 if one is not selected.
+ *
+ * @param player Player instance
+ * @return Audio stream index or -1
+ */
+KIT_API int Kit_GetPlayerAudioStream(const Kit_Player *player);
+
+/**
+ * @brief Gets the current subtitle stream index
+ *
+ * Returns the current subtitle stream index or -1 if one is not selected.
+ *
+ * @param player Player instance
+ * @return Subtitle stream index or -1
+ */
+KIT_API int Kit_GetPlayerSubtitleStream(const Kit_Player *player);
+
+/**
+ * @brief Fetches a new video frame from the player
+ *
+ * Note that the output texture must be previously allocated and valid.
+ *
+ * It is important to select the correct texture format and size. If you pick a different
+ * texture format or size from what the decoder outputs, then the decoder will attempt to convert
+ * the frames to fit the texture. This will slow down the decoder a *lot* however, so if possible,
+ * pick the texture format from what Kit_GetPlayerInfo() outputs.
+ *
+ * Access flag for the texture *MUST* always be SDL_TEXTUREACCESS_STATIC! Anything else will lead to
+ * undefined behaviour.
+ *
+ * This function will do nothing if player playback has not been started.
+ *
+ * @param player Player instance
+ * @param texture A previously allocated texture
+ * @return 0 on success, 1 on error
+ */
+KIT_API int Kit_GetPlayerVideoData(Kit_Player *player, SDL_Texture *texture);
+
+/**
+ * @brief Fetches subtitle data from the player
+ *
+ * Output texture will be used as a texture atlas for the subtitle fragments.
+ *
+ * Note that the output texture must be previously allocated and valid. Make sure to have large
+ * enough a texture for the rendering resolution you picked! If your rendering resolution if 4k,
+ * then make sure to have texture sized 4096x4096 etc. This gives the texture room to handle the
+ * worst case subtitle textures. If your resolutions is too small, this function will return
+ * value -1. At that point you can replace your current texture with a bigger one on the fly.
+ *
+ * Note that the texture format for the atlas texture *MUST* be SDL_PIXELFORMAT_RGBA32 and
+ * the access flag *MUST* be set to SDL_TEXTUREACCESS_STATIC for correct rendering.
+ * Using any other format will lead to undefined behaviour. Also, make sure to set scaling quality
+ * to 0 or "nearest" before creating the texture -- otherwise you get artifacts
+ * (see SDL_HINT_RENDER_SCALE_QUALITY).
+ *
+ * This function will do nothing if player playback has not been started.
+ *
+ * For example:
+ * ```
+ * SDL_Rect sources[256];
+ * SDL_Rect targets[256];
+ * int got = Kit_GetPlayerSubtitleData(player, subtitle_tex, sources, targets, 256);
+ * for(int i = 0; i < got; i++) {
+ * SDL_RenderCopy(renderer, subtitle_tex, &sources[i], &targets[i]);
+ * }
+ * ```
+ *
+ * @param player Player instance
+ * @param texture A previously allocated texture
+ * @param sources List of source rectangles to copy fropm
+ * @param targets List of target rectangles to render
+ * @param limit Defines the maximum size of your rectangle lists
+ * @return Number of sources or <0 on error
+ */
+KIT_API int Kit_GetPlayerSubtitleData(Kit_Player *player,
+ SDL_Texture *texture,
+ SDL_Rect *sources,
+ SDL_Rect *targets,
+ int limit);
+
+/**
+ * @brief Fetches audio data from the player
+ *
+ * Note that the output buffer must be previously allocated.
+ *
+ * Outputted audio data will be precisely what is described by the output format struct given
+ * by Kit_GetPlayerInfo().
+ *
+ * This function will attemt to read the maximum allowed amount of data allowed by the length
+ * argument. It is possible however that there is not enough data available, at which point
+ * this function will read less and return value may differ from maximum allowed value.
+ * Return value 0 should be taken as a hint that there is nothing available.
+ *
+ * This function will do nothing if player playback has not been started.
+ *
+ * @param player Player instance
+ * @param buffer Buffer to read into
+ * @param length Maximum length of the buffer
+ * @return Amount of data that was read, <0 on error.
+ */
+KIT_API int Kit_GetPlayerAudioData(Kit_Player *player, unsigned char *buffer, int length);
+
+/**
+ * @brief Fetches information about the currently selected streams
+ *
+ * This function should be used to fetch codec information and output format data from the player
+ * before creating textures and setting up audio outputs.
+ *
+ * @param player Player instance
+ * @param info A previously allocated Kit_PlayerInfo instance
+ */
KIT_API void Kit_GetPlayerInfo(const Kit_Player *player, Kit_PlayerInfo *info);
+/**
+ * @brief Returns the current state of the player
+ *
+ * @param player Player instance
+ * @return Current state of the player, see Kit_PlayerState
+ */
KIT_API Kit_PlayerState Kit_GetPlayerState(const Kit_Player *player);
+
+/**
+ * @brief Starts playback
+ *
+ * State shifts:
+ * - If player is already playing, will do nothing.
+ * - If player is paused, will resume playback.
+ * - If player is stopped, will begin playback (and background decoding).
+ *
+ * @param player Player instance
+ */
KIT_API void Kit_PlayerPlay(Kit_Player *player);
+
+/**
+ * @brief Stops playback
+ *
+ * State shifts:
+ * - If player is already stopped, will do nothing.
+ * - If player is paused, will stop playback.
+ * - If player is started, will stop playback (and background decoding).
+ *
+ * @param player Player instance
+ */
KIT_API void Kit_PlayerStop(Kit_Player *player);
+
+/**
+ * @brief Pauses playback
+ *
+ * State shifts:
+ * - If player is already paused, will do nothing.
+ * - If player is stopped, will do nothing.
+ * - If player is started, will pause playback (and background decoding).
+ *
+ * @param player Player instance
+ */
KIT_API void Kit_PlayerPause(Kit_Player *player);
+/**
+ * @brief Seek to timestamp
+ *
+ * Rewinds or forwards video/audio playback to the given timestamp (in seconds).
+ *
+ * This may not work for network or custom sources!
+ *
+ * @param player Player instance
+ * @param time Timestamp to seek to in seconds
+ * @return 0 on success, 1 on failure.
+ */
KIT_API int Kit_PlayerSeek(Kit_Player *player, double time);
+
+/**
+ * @brief Get the duration of the source
+ *
+ * Returns the duration of the source in seconds
+ *
+ * @param player Player instance
+ * @return Duration
+ */
KIT_API double Kit_GetPlayerDuration(const Kit_Player *player);
+
+/**
+ * @brief Get the current position of the playback
+ *
+ * Returns the position of the playback in seconds
+ *
+ * @param player Player instance
+ * @return Position
+ */
KIT_API double Kit_GetPlayerPosition(const Kit_Player *player);
#ifdef __cplusplus
diff --git a/include/kitchensink/kitsource.h b/include/kitchensink/kitsource.h
index ed1711f..9b744ca 100644
--- a/include/kitchensink/kitsource.h
+++ b/include/kitchensink/kitsource.h
@@ -1,15 +1,27 @@
#ifndef KITSOURCE_H
#define KITSOURCE_H
+/**
+ * @brief Video/Audio source file handling
+ *
+ * @file kitsource.h
+ * @author Tuomas Virtanen
+ * @date 2018-06-27
+ */
+
+#include <inttypes.h>
+#include <SDL_rwops.h>
#include "kitchensink/kitconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
-#define KIT_CODECNAMESIZE 32
-#define KIT_CODECLONGNAMESIZE 128
-
+/**
+ * @brief Type of the stream.
+ *
+ * This is used by Kit_SourceStreamInfo and Kit_GetSourceStreamInfo().
+ */
typedef enum Kit_StreamType {
KIT_STREAMTYPE_UNKNOWN, ///< Unknown stream type
KIT_STREAMTYPE_VIDEO, ///< Video stream
@@ -19,26 +31,202 @@ typedef enum Kit_StreamType {
KIT_STREAMTYPE_ATTACHMENT ///< Attachment stream (images, etc)
} Kit_StreamType;
+/**
+ * @brief Audio/video source.
+ *
+ * Should be created using Kit_CreateSourceFromUrl() or Kit_CreateSourceFromCustom(), and
+ * closed with Kit_CloseSource().
+ *
+ * Source must exist for the whole duration of using a player. You must take care of closing the source
+ * yourself after you are done with it!
+ */
typedef struct Kit_Source {
- int astream_idx; ///< Audio stream index
- int vstream_idx; ///< Video stream index
- int sstream_idx; ///< Subtitle stream index
void *format_ctx; ///< FFmpeg: Videostream format context
+ void *avio_ctx; ///< FFmpeg: AVIO context
} Kit_Source;
-typedef struct Kit_Stream {
+/**
+ * @brief Information for a source stream.
+ *
+ * Fetch information by using Kit_GetSourceStreamInfo().
+ */
+typedef struct Kit_SourceStreamInfo {
int index; ///< Stream index
Kit_StreamType type; ///< Stream type
-} Kit_StreamInfo;
+} Kit_SourceStreamInfo;
+
+/**
+ * @brief Callback function type for reading data stream
+ *
+ * Used by Kit_CreateSourceFromCustom() for reading data from user defined source.
+ *
+ * A custom reader function must accept three arguments:
+ * - userdata, this is the same data as set as last argument for Kit_CreateSourceFromCustom
+ * - buf, a buffer the data must be copied into
+ * - size, how much data you are expected to provide at maximum.
+ *
+ * The function must return the amount of bytes copied to the buffer or <0 on error.
+ *
+ * Note that this callback is passed directly to ffmpeg avio, so please refer to ffmpeg documentation
+ * for any further details.
+ */
+typedef int (*Kit_ReadCallback)(void *userdata, uint8_t *buf, int size);
+
+/**
+ * @brief Callback function type for seeking data strema
+ *
+ * Used by Kit_CreateSourceFromCustom() for seeking a user defined source.
+ *
+ * A custom seeking function must accept three arguments:
+ * - userdata, this is the same data as set as last argument for Kit_CreateSourceFromCustom
+ * - offset, an seeking offset in bytes
+ * - whence, reference position for the offset.
+ *
+ * Whence parameter can be one of the standard fseek values or optionally AVSEEK_SIZE.
+ * - SEEK_SET: Reference position is beginning of file
+ * - SEEK_CUR: Reference position is the current position of the file pointer
+ * - SEEK_END: Reference position is the end of the file
+ * - AVSEEK_SIZE: Optional. Does not seek, instead finds the size of the source file.
+ * - AVSEEK_FORCE: Optional. Suggests that seeking should be done at any cost. May be passed alongside
+ * any of the SEEK_* flags, eg. SEEK_SET|AVSEEK_FORCE.
+ *
+ * The function must return the position (in bytes) we seeked to or <0 on error or on unsupported operation.
+ *
+ * Note that this callback is passed directly to ffmpeg avio, so please refer to ffmpeg documentation
+ * for any further details.
+ */
+typedef int64_t (*Kit_SeekCallback)(void *userdata, int64_t offset, int whence);
+
+/**
+ * @brief Create a new source from a given url
+ *
+ * This can be used to load video/audio from a file or network resource. If you wish to
+ * use network resources, make sure the library has been initialized using KIT_INIT_NETWORK flag.
+ *
+ * This function will return an initialized Kit_Source on success. Note that you need to manually
+ * free the source when it's no longer needed by calling Kit_CloseSource().
+ *
+ * On failure, this function will return NULL, and further error data is available via Kit_GetError().
+ *
+ * For example:
+ * ```
+ * if(Kit_CreateSourceFromUrl(filename) == NULL) {
+ * fprintf(stderr, "Error: %s\n", Kit_GetError());
+ * return 1;
+ * }
+ * ```
+ *
+ * @param url File path or URL to a video/audio resource
+ * @return Returns an initialized Kit_Source* on success or NULL on failure
+ */
+KIT_API Kit_Source* Kit_CreateSourceFromUrl(const char *url);
-KIT_API Kit_Source* Kit_CreateSourceFromUrl(const char *path);
+/**
+ * @brief Create a new source from custom data
+ *
+ * This can be used to load data from any resource via the given read and seek functions.
+ *
+ * This function will return an initialized Kit_Source on success. Note that you need to manually
+ * free the source when it's no longer needed by calling Kit_CloseSource().
+ *
+ * On failure, this function will return NULL, and further error data is available via Kit_GetError().
+ *
+ * For example:
+ * ```
+ * if(Kit_CreateSourceFromCustom(read_fn, seek_fn, fp) == NULL) {
+ * fprintf(stderr, "Error: %s\n", Kit_GetError());
+ * return 1;
+ * }
+ * ```
+ *
+ * @param read_cb Read function callback
+ * @param seek_cb Seek function callback
+ * @param userdata Any data (or NULL). Will be passed to read_cb and/or seek_cb functions as-is.
+ * @return Returns an initialized Kit_Source* on success or NULL on failure
+ */
+KIT_API Kit_Source* Kit_CreateSourceFromCustom(Kit_ReadCallback read_cb, Kit_SeekCallback seek_cb, void *userdata);
+
+/**
+ * @brief Create a new source from SDL RWops struct
+ *
+ * Can be used to read data from SDL compatible sources.
+ *
+ * This function will return an initialized Kit_Source on success. Note that you need to manually
+ * free the source when it's no longer needed by calling Kit_CloseSource().
+ *
+ * On failure, this function will return NULL, and further error data is available via Kit_GetError().
+ *
+ * Note that the RWops struct must exist during the whole lifetime of the source, and you must take
+ * care of freeing the rwops after it's no longer needed.
+ *
+ * For example:
+ * ```
+ * SDL_RWops *rw = SDL_RWFromFile("myvideo.mkv", "rb");
+ * if(Kit_CreateSourceFromRW(rw) == NULL) {
+ * fprintf(stderr, "Error: %s\n", Kit_GetError());
+ * return 1;
+ * }
+ * ```
+ *
+ * @param rw_ops Initialized RWOps
+ * @return KIT_API* Kit_CreateSourceFromRW
+ */
+KIT_API Kit_Source* Kit_CreateSourceFromRW(SDL_RWops *rw_ops);
+
+/**
+ * @brief Closes a previously initialized source
+ *
+ * Closes a Kit_Source that was previously created by Kit_CreateSourceFromUrl() or Kit_CreateSourceFromCustom()
+ * and frees up all memory and resources used by it. Using the source for anything after this will
+ * lead to undefined behaviour.
+ *
+ * Passing NULL as argument is valid, and will do nothing.
+ *
+ * @param src Previously initialized Kit_Source to close
+ */
KIT_API void Kit_CloseSource(Kit_Source *src);
-KIT_API int Kit_GetSourceStreamInfo(const Kit_Source *src, Kit_StreamInfo *info, int index);
+/**
+ * @brief Fetches stream information for a given stream index
+ *
+ * Sets fields for given Kit_SourceStreamInfo with information about the stream.
+ *
+ * For example:
+ * ```
+ * Kit_SourceStreamInfo stream;
+ * if(Kit_GetSourceStreamInfo(source, &stream, 0) == 1) {
+ * fprintf(stderr, "Error: %s\n", Kit_GetError());
+ * return 1;
+ * }
+ * fprintf(stderr, "Stream type: %s\n", Kit_GetKitStreamTypeString(stream.type))
+ * ```
+ *
+ * @param src Source to query from
+ * @param info A previously allocated Kit_SourceStreamInfo to fill out
+ * @param index Stream index (starting from 0)
+ * @return 0 on success, 1 on error.
+ */
+KIT_API int Kit_GetSourceStreamInfo(const Kit_Source *src, Kit_SourceStreamInfo *info, int index);
+
+/**
+ * @brief Gets the amount of streams in source
+ *
+ * @param src Source to query from
+ * @return Number of streams in the source
+ */
KIT_API int Kit_GetSourceStreamCount(const Kit_Source *src);
+
+/**
+ * @brief Gets the best stream index for a given stream type.
+ *
+ * Find the best stream index for a given stream type, if one exists. If there is no
+ * stream for the wanted type, will return -1.
+ *
+ * @param src Source to query from
+ * @param type Stream type
+ * @return Index number on success (>=0), -1 on error.
+ */
KIT_API int Kit_GetBestSourceStream(const Kit_Source *src, const Kit_StreamType type);
-KIT_API int Kit_SetSourceStream(Kit_Source *src, const Kit_StreamType type, int index);
-KIT_API int Kit_GetSourceStream(const Kit_Source *src, const Kit_StreamType type);
#ifdef __cplusplus
}
diff --git a/include/kitchensink/kitutils.h b/include/kitchensink/kitutils.h
index af3307c..af0e14b 100644
--- a/include/kitchensink/kitutils.h
+++ b/include/kitchensink/kitutils.h
@@ -1,14 +1,42 @@
#ifndef KITUTILS_H
#define KITUTILS_H
+/**
+ * @brief Helpful utilities
+ *
+ * @file kitutils.h
+ * @author Tuomas Virtanen
+ * @date 2018-06-25
+ */
+
#include "kitchensink/kitconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
+/**
+ * @brief Returns a descriptive string for SDL audio format types
+ *
+ * @param type SDL_AudioFormat
+ * @return Format string, eg. "AUDIO_S8".
+ */
KIT_API const char* Kit_GetSDLAudioFormatString(unsigned int type);
+
+/**
+ * @brief Returns a descriptive string for SDL pixel format types
+ *
+ * @param type SDL_PixelFormat
+ * @return Format string, eg. "SDL_PIXELFORMAT_YV12"
+ */
KIT_API const char* Kit_GetSDLPixelFormatString(unsigned int type);
+
+/**
+ * @brief Returns a descriptibe string for Kitchensink stream types
+ *
+ * @param type Kit_StreamType
+ * @return Format string, eg. "KIT_STREAMTYPE_VIDEO"
+ */
KIT_API const char* Kit_GetKitStreamTypeString(unsigned int type);
#ifdef __cplusplus