summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTuomas Virtanen <katajakasa@gmail.com>2018-06-24 23:30:42 +0300
committerTuomas Virtanen <katajakasa@gmail.com>2018-06-24 23:30:42 +0300
commitd7d5cb75e6fa7f0d2eaeb9cdaf2812dc4c5be466 (patch)
tree63a68f7fceb4d4a9c06a0e5054375da0477f081f
parent1d06ec23f264e18a188bf46b72c8794c82c4b89e (diff)
API rework #36, #37
-rw-r--r--examples/example_audio.c23
-rw-r--r--examples/example_complex.c73
-rw-r--r--examples/example_custom.c19
-rw-r--r--examples/example_simple.c19
-rw-r--r--include/kitchensink/internal/audio/kitaudio.h5
-rw-r--r--include/kitchensink/internal/kitdecoder.h24
-rw-r--r--include/kitchensink/internal/kitlibstate.h5
-rw-r--r--include/kitchensink/internal/subtitle/kitsubtitle.h5
-rw-r--r--include/kitchensink/internal/subtitle/renderers/kitsubrenderer.h1
-rw-r--r--include/kitchensink/internal/video/kitvideo.h7
-rw-r--r--include/kitchensink/kitchensink.h3
-rw-r--r--include/kitchensink/kitcodec.h21
-rw-r--r--include/kitchensink/kitformat.h24
-rw-r--r--include/kitchensink/kitformats.h38
-rw-r--r--include/kitchensink/kitlib.h22
-rw-r--r--include/kitchensink/kitplayer.h46
-rw-r--r--include/kitchensink/kitsource.h13
-rw-r--r--src/internal/audio/kitaudio.c95
-rw-r--r--src/internal/kitdecoder.c33
-rw-r--r--src/internal/kitlibstate.c2
-rw-r--r--src/internal/subtitle/kitsubtitle.c50
-rw-r--r--src/internal/subtitle/renderers/kitsubass.c2
-rw-r--r--src/internal/video/kitvideo.c38
-rw-r--r--src/kitlib.c51
-rw-r--r--src/kitplayer.c198
-rw-r--r--src/kitsource.c2
26 files changed, 468 insertions, 351 deletions
diff --git a/examples/example_audio.c b/examples/example_audio.c
index 51bee13..80c8dab 100644
--- a/examples/example_audio.c
+++ b/examples/example_audio.c
@@ -63,7 +63,7 @@ int main(int argc, char *argv[]) {
}
// Print stream information
- Kit_StreamInfo sinfo;
+ Kit_SourceStreamInfo sinfo;
fprintf(stderr, "Source streams:\n");
for(int i = 0; i < Kit_GetSourceStreamCount(src); i++) {
err = Kit_GetSourceStreamInfo(src, &sinfo, i);
@@ -90,25 +90,26 @@ int main(int argc, char *argv[]) {
Kit_PlayerInfo pinfo;
Kit_GetPlayerInfo(player, &pinfo);
- if(!pinfo.audio.is_enabled) {
+ // Make sure there is audio in the file to play first.
+ if(Kit_GetPlayerAudioStream(player) == -1) {
fprintf(stderr, "File contains no audio!\n");
return 1;
}
fprintf(stderr, "Media information:\n");
fprintf(stderr, " * Audio: %s (%s), %dHz, %dch, %db, %s\n",
- pinfo.acodec,
- pinfo.acodec_name,
- pinfo.audio.samplerate,
- pinfo.audio.channels,
- pinfo.audio.bytes,
- pinfo.audio.is_signed ? "signed" : "unsigned");
+ pinfo.audio.codec.name,
+ pinfo.audio.codec.description,
+ pinfo.audio.output.samplerate,
+ pinfo.audio.output.channels,
+ pinfo.audio.output.bytes,
+ pinfo.audio.output.is_signed ? "signed" : "unsigned");
// Init audio
SDL_memset(&wanted_spec, 0, sizeof(wanted_spec));
- wanted_spec.freq = pinfo.audio.samplerate;
- wanted_spec.format = pinfo.audio.format;
- wanted_spec.channels = pinfo.audio.channels;
+ wanted_spec.freq = pinfo.audio.output.samplerate;
+ wanted_spec.format = pinfo.audio.output.format;
+ wanted_spec.channels = pinfo.audio.output.channels;
audio_dev = SDL_OpenAudioDevice(NULL, 0, &wanted_spec, &audio_spec, 0);
SDL_PauseAudioDevice(audio_dev, 0);
diff --git a/examples/example_complex.c b/examples/example_complex.c
index b49f980..bd337bb 100644
--- a/examples/example_complex.c
+++ b/examples/example_complex.c
@@ -109,6 +109,10 @@ int main(int argc, char *argv[]) {
return 1;
}
+ // Allow Kit to use more threads
+ Kit_SetHint(KIT_HINT_THREAD_COUNT, SDL_GetCPUCount() <= 2 ? SDL_GetCPUCount() : 2);
+ Kit_SetHint(KIT_HINT_FONT_HINTING, KIT_FONT_HINTING_LIGHT);
+
// Open up the sourcefile.
// This can be a local file, network url, ...
src = Kit_CreateSourceFromUrl(filename);
@@ -118,7 +122,7 @@ int main(int argc, char *argv[]) {
}
// Print stream information
- Kit_StreamInfo sinfo;
+ Kit_SourceStreamInfo sinfo;
fprintf(stderr, "Source streams:\n");
for(int i = 0; i < Kit_GetSourceStreamCount(src); i++) {
err = Kit_GetSourceStreamInfo(src, &sinfo, i);
@@ -146,55 +150,61 @@ int main(int argc, char *argv[]) {
Kit_PlayerInfo pinfo;
Kit_GetPlayerInfo(player, &pinfo);
- if(!pinfo.video.is_enabled) {
+ // Make sure there is video in the file to play first.
+ if(Kit_GetPlayerVideoStream(player) == -1) {
fprintf(stderr, "File contains no video!\n");
return 1;
}
fprintf(stderr, "Media information:\n");
- if(pinfo.audio.is_enabled) {
- fprintf(stderr, " * Audio: %s (%s), %dHz, %dch, %db, %s\n",
- pinfo.acodec,
- pinfo.acodec_name,
- pinfo.audio.samplerate,
- pinfo.audio.channels,
- pinfo.audio.bytes,
- pinfo.audio.is_signed ? "signed" : "unsigned");
+ if(Kit_GetPlayerAudioStream(player) >= 0) {
+ fprintf(stderr, " * Audio: %s (%s), threads=%d, %dHz, %dch, %db, %s\n",
+ pinfo.audio.codec.name,
+ pinfo.audio.codec.description,
+ pinfo.video.codec.threads,
+ pinfo.audio.output.samplerate,
+ pinfo.audio.output.channels,
+ pinfo.audio.output.bytes,
+ pinfo.audio.output.is_signed ? "signed" : "unsigned");
+ }
+ if(Kit_GetPlayerVideoStream(player) >= 0) {
+ fprintf(stderr, " * Video: %s (%s), threads=%d, %dx%d\n",
+ pinfo.video.codec.name,
+ pinfo.video.codec.description,
+ pinfo.video.codec.threads,
+ pinfo.video.output.width,
+ pinfo.video.output.height);
}
- fprintf(stderr, " * Video: %s (%s), %dx%d\n",
- pinfo.vcodec,
- pinfo.vcodec_name,
- pinfo.video.width,
- pinfo.video.height);
- if(pinfo.subtitle.is_enabled) {
- fprintf(stderr, " * Subtitle: %s (%s)\n",
- pinfo.scodec,
- pinfo.scodec_name);
+ if(Kit_GetPlayerSubtitleStream(player) >= 0) {
+ fprintf(stderr, " * Subtitle: %s (%s), threads=%d\n",
+ pinfo.subtitle.codec.name,
+ pinfo.subtitle.codec.description,
+ pinfo.video.codec.threads);
}
fprintf(stderr, "Duration: %f seconds\n", Kit_GetPlayerDuration(player));
// Init audio
SDL_memset(&wanted_spec, 0, sizeof(wanted_spec));
- wanted_spec.freq = pinfo.audio.samplerate;
- wanted_spec.format = pinfo.audio.format;
- wanted_spec.channels = pinfo.audio.channels;
+ wanted_spec.freq = pinfo.audio.output.samplerate;
+ wanted_spec.format = pinfo.audio.output.format;
+ wanted_spec.channels = pinfo.audio.output.channels;
audio_dev = SDL_OpenAudioDevice(NULL, 0, &wanted_spec, &audio_spec, 0);
SDL_PauseAudioDevice(audio_dev, 0);
// Print some format info
- fprintf(stderr, "Texture type: %s\n", Kit_GetSDLPixelFormatString(pinfo.video.format));
- fprintf(stderr, "Audio format: %s\n", Kit_GetSDLAudioFormatString(pinfo.audio.format));
- fprintf(stderr, "Subtitle format: %s\n", Kit_GetSDLPixelFormatString(pinfo.subtitle.format));
+ fprintf(stderr, "Texture type: %s\n", Kit_GetSDLPixelFormatString(pinfo.video.output.format));
+ fprintf(stderr, "Audio format: %s\n", Kit_GetSDLAudioFormatString(pinfo.audio.output.format));
+ fprintf(stderr, "Subtitle format: %s\n", Kit_GetSDLPixelFormatString(pinfo.subtitle.output.format));
fflush(stderr);
// Initialize video texture. This will probably end up as YV12 most of the time.
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
SDL_Texture *video_tex = SDL_CreateTexture(
renderer,
- pinfo.video.format,
+ pinfo.video.output.format,
SDL_TEXTUREACCESS_STATIC,
- pinfo.video.width,
- pinfo.video.height);
+ pinfo.video.output.width,
+ pinfo.video.output.height);
if(video_tex == NULL) {
fprintf(stderr, "Error while attempting to create a video texture\n");
return 1;
@@ -204,7 +214,7 @@ int main(int argc, char *argv[]) {
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest"); // Always nearest for atlas operations
SDL_Texture *subtitle_tex = SDL_CreateTexture(
renderer,
- pinfo.subtitle.format,
+ pinfo.subtitle.output.format,
SDL_TEXTUREACCESS_STATIC,
ATLAS_WIDTH, ATLAS_HEIGHT);
if(subtitle_tex == NULL) {
@@ -226,7 +236,7 @@ int main(int argc, char *argv[]) {
int screen_w = 0;
int screen_h = 0;
SDL_GetWindowSize(window, &screen_w, &screen_h);
- find_viewport_size(screen_w, screen_h, pinfo.video.width, pinfo.video.height, &size_w, &size_h);
+ find_viewport_size(screen_w, screen_h, pinfo.video.output.width, pinfo.video.output.height, &size_w, &size_h);
SDL_RenderSetLogicalSize(renderer, size_w, size_h);
Kit_SetPlayerScreenSize(player, size_w, size_h);
bool fullscreen = false;
@@ -268,7 +278,8 @@ int main(int argc, char *argv[]) {
switch(event.window.event) {
case SDL_WINDOWEVENT_SIZE_CHANGED:
SDL_GetWindowSize(window, &screen_w, &screen_h);
- find_viewport_size(screen_w, screen_h, pinfo.video.width, pinfo.video.height, &size_w, &size_h);
+ find_viewport_size(
+ screen_w, screen_h, pinfo.video.output.width, pinfo.video.output.height, &size_w, &size_h);
SDL_RenderSetLogicalSize(renderer, size_w, size_h);
Kit_SetPlayerScreenSize(player, size_w, size_h);
break;
diff --git a/examples/example_custom.c b/examples/example_custom.c
index 7e1d90b..507efb1 100644
--- a/examples/example_custom.c
+++ b/examples/example_custom.c
@@ -108,16 +108,17 @@ int main(int argc, char *argv[]) {
Kit_PlayerInfo pinfo;
Kit_GetPlayerInfo(player, &pinfo);
- if(!pinfo.video.is_enabled) {
+ // Make sure there is video in the file to play first.
+ if(Kit_GetPlayerVideoStream(player) == -1) {
fprintf(stderr, "File contains no video!\n");
return 1;
}
// Init audio
SDL_memset(&wanted_spec, 0, sizeof(wanted_spec));
- wanted_spec.freq = pinfo.audio.samplerate;
- wanted_spec.format = pinfo.audio.format;
- wanted_spec.channels = pinfo.audio.channels;
+ wanted_spec.freq = pinfo.audio.output.samplerate;
+ wanted_spec.format = pinfo.audio.output.format;
+ wanted_spec.channels = pinfo.audio.output.channels;
audio_dev = SDL_OpenAudioDevice(NULL, 0, &wanted_spec, &audio_spec, 0);
SDL_PauseAudioDevice(audio_dev, 0);
@@ -125,10 +126,10 @@ int main(int argc, char *argv[]) {
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
SDL_Texture *video_tex = SDL_CreateTexture(
renderer,
- pinfo.video.format,
+ pinfo.video.output.format,
SDL_TEXTUREACCESS_STATIC,
- pinfo.video.width,
- pinfo.video.height);
+ pinfo.video.output.width,
+ pinfo.video.output.height);
if(video_tex == NULL) {
fprintf(stderr, "Error while attempting to create a video texture\n");
return 1;
@@ -138,7 +139,7 @@ int main(int argc, char *argv[]) {
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest"); // Always nearest for atlas operations
SDL_Texture *subtitle_tex = SDL_CreateTexture(
renderer,
- pinfo.subtitle.format,
+ pinfo.subtitle.output.format,
SDL_TEXTUREACCESS_STATIC,
ATLAS_WIDTH, ATLAS_HEIGHT);
if(subtitle_tex == NULL) {
@@ -153,7 +154,7 @@ int main(int argc, char *argv[]) {
Kit_PlayerPlay(player);
// Get movie area size
- SDL_RenderSetLogicalSize(renderer, pinfo.video.width, pinfo.video.height);
+ SDL_RenderSetLogicalSize(renderer, pinfo.video.output.width, pinfo.video.output.height);
while(run) {
if(Kit_GetPlayerState(player) == KIT_STOPPED) {
run = false;
diff --git a/examples/example_simple.c b/examples/example_simple.c
index 0221863..d3b7146 100644
--- a/examples/example_simple.c
+++ b/examples/example_simple.c
@@ -85,16 +85,17 @@ int main(int argc, char *argv[]) {
Kit_PlayerInfo pinfo;
Kit_GetPlayerInfo(player, &pinfo);
- if(!pinfo.video.is_enabled) {
+ // Make sure there is video in the file to play first.
+ if(Kit_GetPlayerVideoStream(player) == -1) {
fprintf(stderr, "File contains no video!\n");
return 1;
}
// Init audio
SDL_memset(&wanted_spec, 0, sizeof(wanted_spec));
- wanted_spec.freq = pinfo.audio.samplerate;
- wanted_spec.format = pinfo.audio.format;
- wanted_spec.channels = pinfo.audio.channels;
+ wanted_spec.freq = pinfo.audio.output.samplerate;
+ wanted_spec.format = pinfo.audio.output.format;
+ wanted_spec.channels = pinfo.audio.output.channels;
audio_dev = SDL_OpenAudioDevice(NULL, 0, &wanted_spec, &audio_spec, 0);
SDL_PauseAudioDevice(audio_dev, 0);
@@ -102,10 +103,10 @@ int main(int argc, char *argv[]) {
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
SDL_Texture *video_tex = SDL_CreateTexture(
renderer,
- pinfo.video.format,
+ pinfo.video.output.format,
SDL_TEXTUREACCESS_STATIC,
- pinfo.video.width,
- pinfo.video.height);
+ pinfo.video.output.width,
+ pinfo.video.output.height);
if(video_tex == NULL) {
fprintf(stderr, "Error while attempting to create a video texture\n");
return 1;
@@ -115,7 +116,7 @@ int main(int argc, char *argv[]) {
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest"); // Always nearest for atlas operations
SDL_Texture *subtitle_tex = SDL_CreateTexture(
renderer,
- pinfo.subtitle.format,
+ pinfo.subtitle.output.format,
SDL_TEXTUREACCESS_STATIC,
ATLAS_WIDTH, ATLAS_HEIGHT);
if(subtitle_tex == NULL) {
@@ -130,7 +131,7 @@ int main(int argc, char *argv[]) {
Kit_PlayerPlay(player);
// Get movie area size
- SDL_RenderSetLogicalSize(renderer, pinfo.video.width, pinfo.video.height);
+ SDL_RenderSetLogicalSize(renderer, pinfo.video.output.width, pinfo.video.output.height);
while(run) {
if(Kit_GetPlayerState(player) == KIT_STOPPED) {
run = false;
diff --git a/include/kitchensink/internal/audio/kitaudio.h b/include/kitchensink/internal/audio/kitaudio.h
index 105c9f6..e42770b 100644
--- a/include/kitchensink/internal/audio/kitaudio.h
+++ b/include/kitchensink/internal/audio/kitaudio.h
@@ -2,11 +2,10 @@
#define KITAUDIO_H
#include "kitchensink/kitconfig.h"
-#include "kitchensink/kitformats.h"
-#include "kitchensink/kitplayer.h"
+#include "kitchensink/kitsource.h"
#include "kitchensink/internal/kitdecoder.h"
-KIT_LOCAL Kit_Decoder* Kit_CreateAudioDecoder(const Kit_Source *src, int stream_index, Kit_AudioFormat *format);
+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
index b4b3f36..0e89aea 100644
--- a/include/kitchensink/internal/kitdecoder.h
+++ b/include/kitchensink/internal/kitdecoder.h
@@ -7,6 +7,8 @@
#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"
@@ -24,6 +26,7 @@ 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)
@@ -37,24 +40,33 @@ KIT_LOCAL struct Kit_Decoder {
};
KIT_LOCAL Kit_Decoder* Kit_CreateDecoder(const Kit_Source *src, int stream_index,
- int out_b_size, dec_free_packet_cb free_out_cb);
-KIT_LOCAL int Kit_SetDecoderStreamIndex(Kit_Decoder *dec, 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 void Kit_ClearDecoderBuffers(Kit_Decoder *dec);
KIT_LOCAL int Kit_LockDecoderOutput(Kit_Decoder *dec);
KIT_LOCAL void Kit_UnlockDecoderOutput(Kit_Decoder *dec);
-KIT_LOCAL int Kit_RunDecoder(Kit_Decoder *dec);
-KIT_LOCAL void Kit_ClearDecoderInput(Kit_Decoder *dec);
KIT_LOCAL void Kit_ClearDecoderOutput(Kit_Decoder *dec);
-KIT_LOCAL void Kit_CloseDecoder(Kit_Decoder *dec);
+
#endif // KITDECODER_H
diff --git a/include/kitchensink/internal/kitlibstate.h b/include/kitchensink/internal/kitlibstate.h
index ad515b9..b92cebb 100644
--- a/include/kitchensink/internal/kitlibstate.h
+++ b/include/kitchensink/internal/kitlibstate.h
@@ -6,6 +6,11 @@
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;
diff --git a/include/kitchensink/internal/subtitle/kitsubtitle.h b/include/kitchensink/internal/subtitle/kitsubtitle.h
index 9f83e3d..8de101b 100644
--- a/include/kitchensink/internal/subtitle/kitsubtitle.h
+++ b/include/kitchensink/internal/subtitle/kitsubtitle.h
@@ -4,12 +4,11 @@
#include <SDL2/SDL_render.h>
#include "kitchensink/kitconfig.h"
-#include "kitchensink/kitformats.h"
-#include "kitchensink/kitplayer.h"
+#include "kitchensink/kitsource.h"
#include "kitchensink/internal/kitdecoder.h"
KIT_LOCAL Kit_Decoder* Kit_CreateSubtitleDecoder(
- const Kit_Source *src, int stream_index, Kit_SubtitleFormat *format, int video_w, int video_h, int screen_w, int screen_h);
+ const Kit_Source *src, int stream_index, int video_w, int video_h, int screen_w, int screen_h);
KIT_LOCAL int Kit_GetSubtitleDecoderData(
Kit_Decoder *dec, SDL_Texture *texture, SDL_Rect *sources, SDL_Rect *targets, int limit);
KIT_LOCAL void Kit_SetSubtitleDecoderSize(Kit_Decoder *dec, int w, int h);
diff --git a/include/kitchensink/internal/subtitle/renderers/kitsubrenderer.h b/include/kitchensink/internal/subtitle/renderers/kitsubrenderer.h
index 84b815b..e07aa55 100644
--- a/include/kitchensink/internal/subtitle/renderers/kitsubrenderer.h
+++ b/include/kitchensink/internal/subtitle/renderers/kitsubrenderer.h
@@ -2,7 +2,6 @@
#define KITSUBRENDERER_H
#include "kitchensink/kitsource.h"
-#include "kitchensink/kitformats.h"
typedef struct Kit_SubtitleRenderer Kit_SubtitleRenderer;
typedef struct Kit_TextureAtlas Kit_TextureAtlas;
diff --git a/include/kitchensink/internal/video/kitvideo.h b/include/kitchensink/internal/video/kitvideo.h
index 1e158a7..0733177 100644
--- a/include/kitchensink/internal/video/kitvideo.h
+++ b/include/kitchensink/internal/video/kitvideo.h
@@ -1,12 +1,13 @@
#ifndef KITVIDEO_H
#define KITVIDEO_H
+#include <SDL2/SDL_render.h>
+
#include "kitchensink/kitconfig.h"
-#include "kitchensink/kitformats.h"
-#include "kitchensink/kitplayer.h"
+#include "kitchensink/kitsource.h"
#include "kitchensink/internal/kitdecoder.h"
-KIT_LOCAL Kit_Decoder* Kit_CreateVideoDecoder(const Kit_Source *src, int stream_index, Kit_VideoFormat *format);
+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 6c5da35..568c0d8 100644
--- a/include/kitchensink/kitchensink.h
+++ b/include/kitchensink/kitchensink.h
@@ -3,7 +3,8 @@
#include "kitchensink/kitlib.h"
#include "kitchensink/kiterror.h"
-#include "kitchensink/kitformats.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..76b53a4
--- /dev/null
+++ b/include/kitchensink/kitcodec.h
@@ -0,0 +1,21 @@
+#ifndef KITCODEC_H
+#define KITCODEC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define KIT_CODEC_NAME_MAX 8
+#define KIT_CODEC_DESC_MAX 48
+
+typedef struct Kit_Codec {
+ unsigned int threads; ///< Currently enabled threads
+ 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/kitformat.h b/include/kitchensink/kitformat.h
new file mode 100644
index 0000000..4c428c5
--- /dev/null
+++ b/include/kitchensink/kitformat.h
@@ -0,0 +1,24 @@
+#ifndef KITFORMAT_H
+#define KITFORMAT_H
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct Kit_OutputFormat {
+ unsigned int format; ///< SDL Format
+ bool is_signed; ///< Signedness (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/kitformats.h b/include/kitchensink/kitformats.h
deleted file mode 100644
index 80bfd4f..0000000
--- a/include/kitchensink/kitformats.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef KITFORMATS_H
-#define KITFORMATS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdbool.h>
-
-typedef struct Kit_AudioFormat {
- int stream_index; ///< 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_index; ///< 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_index; ///< Stream index
- bool is_enabled; ///< Is stream enabled
- unsigned int format; ///< SDL Pixel Format
-} Kit_SubtitleFormat;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // KITFORMATS_H
diff --git a/include/kitchensink/kitlib.h b/include/kitchensink/kitlib.h
index d8c3bb9..85ce2d4 100644
--- a/include/kitchensink/kitlib.h
+++ b/include/kitchensink/kitlib.h
@@ -1,22 +1,34 @@
#ifndef KITLIB_H
#define KITLIB_H
-#include "kitchensink/kiterror.h"
-#include "kitchensink/kitsource.h"
-#include "kitchensink/kitplayer.h"
-#include "kitchensink/kitutils.h"
#include "kitchensink/kitconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
+enum { // These should match libass
+ KIT_FONT_HINTING_NONE = 0,
+ KIT_FONT_HINTING_LIGHT,
+ KIT_FONT_HINTING_NORMAL,
+ KIT_FONT_HINTING_NATIVE,
+ KIT_FONT_HINTING_COUNT
+};
+
typedef struct Kit_Version {
unsigned char major;
unsigned char minor;
unsigned char patch;
} Kit_Version;
+typedef enum Kit_HintType {
+ KIT_HINT_FONT_HINTING,
+ KIT_HINT_THREAD_COUNT,
+ KIT_HINT_VIDEO_BUFFER_FRAMES,
+ KIT_HINT_AUDIO_BUFFER_FRAMES,
+ KIT_HINT_SUBTITLE_BUFFER_FRAMES
+} Kit_HintType;
+
enum {
KIT_INIT_NETWORK = 0x1,
KIT_INIT_ASS = 0x2
@@ -24,6 +36,8 @@ enum {
KIT_API int Kit_Init(unsigned int flags);
KIT_API void Kit_Quit();
+KIT_API void Kit_SetHint(Kit_HintType type, int value);
+KIT_API int Kit_GetHint(Kit_HintType type);
KIT_API void Kit_GetVersion(Kit_Version *version);
#ifdef __cplusplus
diff --git a/include/kitchensink/kitplayer.h b/include/kitchensink/kitplayer.h
index 04e1a0b..27e268d 100644
--- a/include/kitchensink/kitplayer.h
+++ b/include/kitchensink/kitplayer.h
@@ -3,7 +3,8 @@
#include "kitchensink/kitsource.h"
#include "kitchensink/kitconfig.h"
-#include "kitchensink/kitformats.h"
+#include "kitchensink/kitformat.h"
+#include "kitchensink/kitcodec.h"
#include <SDL2/SDL_render.h>
#include <SDL2/SDL_thread.h>
@@ -16,9 +17,6 @@
extern "C" {
#endif
-#define KIT_CODECMAX 16
-#define KIT_CODECNAMEMAX 128
-
typedef enum Kit_PlayerState {
KIT_STOPPED = 0, ///< Playback stopped or has not started yet.
KIT_PLAYING, ///< Playback started & player is actively decoding.
@@ -27,29 +25,23 @@ typedef enum Kit_PlayerState {
} Kit_PlayerState;
typedef struct Kit_Player {
- Kit_PlayerState state; ///< Playback state
- Kit_VideoFormat vformat; ///< Video format information
- Kit_AudioFormat aformat; ///< Audio format information
- Kit_SubtitleFormat sformat; ///< Subtitle format information
- void *audio_dec; ///< Audio decoder context (or NULL)
- void *video_dec; ///< Video decoder context (or NULL)
- void *subtitle_dec; ///< Subtitle decoder context (or NULL)
- SDL_Thread *dec_thread; ///< Decoder thread
- SDL_mutex *dec_lock; ///< Decoder lock
- const Kit_Source *src; ///< Reference to Audio/Video source
- double pause_started; ///< Temporary flag for handling pauses
+ Kit_PlayerState state; ///< Playback state
+ void *decoders[3]; ///< Decoder contexts
+ SDL_Thread *dec_thread; ///< Decoder thread
+ SDL_mutex *dec_lock; ///< Decoder lock
+ const Kit_Source *src; ///< Reference to Audio/Video source
+ double pause_started; ///< Temporary flag for handling pauses
} Kit_Player;
+typedef struct Kit_PlayerStreamInfo {
+ Kit_Codec codec;
+ Kit_OutputFormat output;
+} Kit_PlayerStreamInfo;
+
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;
+ Kit_PlayerStreamInfo audio;
+ Kit_PlayerStreamInfo subtitle;
} Kit_PlayerInfo;
KIT_API Kit_Player* Kit_CreatePlayer(const Kit_Source *src,
@@ -61,9 +53,9 @@ KIT_API Kit_Player* Kit_CreatePlayer(const Kit_Source *src,
KIT_API void Kit_ClosePlayer(Kit_Player *player);
KIT_API void Kit_SetPlayerScreenSize(Kit_Player *player, int w, int h);
-KIT_API int Kit_SetPlayerVideoStream(Kit_Player *player, int index);
-KIT_API int Kit_SetPlayerAudioStream(Kit_Player *player, int index);
-KIT_API int Kit_SetPlayerSubtitleStream(Kit_Player *player, int index);
+KIT_API int Kit_GetPlayerVideoStream(const Kit_Player *player);
+KIT_API int Kit_GetPlayerAudioStream(const Kit_Player *player);
+KIT_API int Kit_GetPlayerSubtitleStream(const Kit_Player *player);
KIT_API int Kit_UpdatePlayer(Kit_Player *player);
KIT_API int Kit_GetPlayerVideoData(Kit_Player *player, SDL_Texture *texture);
diff --git a/include/kitchensink/kitsource.h b/include/kitchensink/kitsource.h
index 0ca8e26..db6ee21 100644
--- a/include/kitchensink/kitsource.h
+++ b/include/kitchensink/kitsource.h
@@ -8,9 +8,6 @@
extern "C" {
#endif
-#define KIT_CODECNAMESIZE 32
-#define KIT_CODECLONGNAMESIZE 128
-
typedef enum Kit_StreamType {
KIT_STREAMTYPE_UNKNOWN, ///< Unknown stream type
KIT_STREAMTYPE_VIDEO, ///< Video stream
@@ -21,14 +18,14 @@ typedef enum Kit_StreamType {
} Kit_StreamType;
typedef struct Kit_Source {
- void *format_ctx; ///< FFmpeg: Videostream format context
- void *avio_ctx; ///< FFmpeg: AVIO context
+ void *format_ctx; ///< FFmpeg: Videostream format context
+ void *avio_ctx; ///< FFmpeg: AVIO context
} Kit_Source;
-typedef struct Kit_StreamInfo {
+typedef struct Kit_SourceStreamInfo {
int index; ///< Stream index
Kit_StreamType type; ///< Stream type
-} Kit_StreamInfo;
+} Kit_SourceStreamInfo;
typedef int (*Kit_ReadCallback)(void*, uint8_t*, int);
typedef int64_t (*Kit_SeekCallback)(void*, int64_t, int);
@@ -37,7 +34,7 @@ KIT_API Kit_Source* Kit_CreateSourceFromUrl(const char *path);
KIT_API Kit_Source* Kit_CreateSourceFromCustom(Kit_ReadCallback read_cb, Kit_SeekCallback seek_cb, void *userdata);
KIT_API void Kit_CloseSource(Kit_Source *src);
-KIT_API int Kit_GetSourceStreamInfo(const Kit_Source *src, Kit_StreamInfo *info, int index);
+KIT_API int Kit_GetSourceStreamInfo(const Kit_Source *src, Kit_SourceStreamInfo *info, int index);
KIT_API int Kit_GetSourceStreamCount(const Kit_Source *src);
KIT_API int Kit_GetBestSourceStream(const Kit_Source *src, const Kit_StreamType type);
diff --git a/src/internal/audio/kitaudio.c b/src/internal/audio/kitaudio.c
index 2071bc5..ec4fc13 100644
--- a/src/internal/audio/kitaudio.c
+++ b/src/internal/audio/kitaudio.c
@@ -8,17 +8,16 @@
#include <SDL2/SDL.h>
#include "kitchensink/kiterror.h"
+#include "kitchensink/internal/kitlibstate.h"
#include "kitchensink/internal/utils/kithelpers.h"
#include "kitchensink/internal/utils/kitbuffer.h"
#include "kitchensink/internal/audio/kitaudio.h"
#include "kitchensink/internal/utils/kitringbuffer.h"
#include "kitchensink/internal/utils/kitlog.h"
-#define KIT_AUDIO_OUT_SIZE 64
#define AUDIO_SYNC_THRESHOLD 0.05
typedef struct Kit_AudioDecoder {
- Kit_AudioFormat *format;
SwrContext *swr;
AVFrame *scratch_frame;
} Kit_AudioDecoder;
@@ -63,24 +62,39 @@ int _FindChannelLayout(uint64_t channel_layout) {
}
}
-void _FindAudioFormat(enum AVSampleFormat fmt, int *bytes, bool *is_signed, unsigned int *format) {
+int _FindBytes(enum AVSampleFormat fmt) {
switch(fmt) {
+ case AV_SAMPLE_FMT_U8P:
case AV_SAMPLE_FMT_U8:
- *bytes = 1;
- *is_signed = false;
- *format = AUDIO_U8;
- break;
+ return 1;
+ case AV_SAMPLE_FMT_S32P:
case AV_SAMPLE_FMT_S32:
- *bytes = 4;
- *is_signed = true;
- *format = AUDIO_S32SYS;
- break;
- case AV_SAMPLE_FMT_S16:
+ return 4;
default:
- *bytes = 2;
- *is_signed = true;
- *format = AUDIO_S16SYS;
- break;
+ return 2;
+ }
+}
+
+int _FindSDLSampleFormat(enum AVSampleFormat fmt) {
+ switch(fmt) {
+ case AV_SAMPLE_FMT_U8P:
+ case AV_SAMPLE_FMT_U8:
+ return AUDIO_U8;
+ case AV_SAMPLE_FMT_S32P:
+ case AV_SAMPLE_FMT_S32:
+ return AUDIO_S32SYS;
+ default:
+ return AUDIO_S16SYS;
+ }
+}
+
+bool _FindSignedness(enum AVSampleFormat fmt) {
+ switch(fmt) {
+ case AV_SAMPLE_FMT_U8P:
+ case AV_SAMPLE_FMT_U8:
+ return false;
+ default:
+ return true;
}
}
@@ -111,16 +125,16 @@ static void dec_decode_audio_cb(Kit_Decoder *dec, AVPacket *in_packet) {
if(frame_finished) {
dst_nb_samples = av_rescale_rnd(
audio_dec->scratch_frame->nb_samples,
- audio_dec->format->samplerate, // Target samplerate
+ dec->output.samplerate, // Target samplerate
dec->codec_ctx->sample_rate, // Source samplerate
AV_ROUND_UP);
av_samples_alloc_array_and_samples(
&dst_data,
&dst_linesize,
- audio_dec->format->channels,
+ dec->output.channels,
dst_nb_samples,
- _FindAVSampleFormat(audio_dec->format->format),
+ _FindAVSampleFormat(dec->output.format),
0);
len2 = swr_convert(
@@ -132,9 +146,9 @@ static void dec_decode_audio_cb(Kit_Decoder *dec, AVPacket *in_packet) {
dst_bufsize = av_samples_get_buffer_size(
&dst_linesize,
- audio_dec->format->channels,
+ dec->output.channels,
len2,
- _FindAVSampleFormat(audio_dec->format->format), 1);
+ _FindAVSampleFormat(dec->output.format), 1);
// Get presentation timestamp
double pts = av_frame_get_best_effort_timestamp(audio_dec->scratch_frame);
@@ -168,30 +182,25 @@ static void dec_close_audio_cb(Kit_Decoder *dec) {
free(audio_dec);
}
-Kit_Decoder* Kit_CreateAudioDecoder(const Kit_Source *src, int stream_index, Kit_AudioFormat *format) {
+Kit_Decoder* Kit_CreateAudioDecoder(const Kit_Source *src, int stream_index) {
assert(src != NULL);
- assert(format != NULL);
if(stream_index < 0) {
return NULL;
}
+ Kit_LibraryState *state = Kit_GetLibraryState();
+
// First the generic decoder component ...
Kit_Decoder *dec = Kit_CreateDecoder(
src,
stream_index,
- KIT_AUDIO_OUT_SIZE,
- free_out_audio_packet_cb);
+ state->audio_buf_frames,
+ free_out_audio_packet_cb,
+ state->thread_count);
if(dec == NULL) {
goto exit_0;
}
- // Find formats
- format->samplerate = dec->codec_ctx->sample_rate;
- format->is_enabled = true;
- format->stream_index = stream_index;
- format->channels = _FindChannelLayout(dec->codec_ctx->channel_layout);
- _FindAudioFormat(dec->codec_ctx->sample_fmt, &format->bytes, &format->is_signed, &format->format);
-
// ... then allocate the audio decoder
Kit_AudioDecoder *audio_dec = calloc(1, sizeof(Kit_AudioDecoder));
if(audio_dec == NULL) {
@@ -205,12 +214,21 @@ Kit_Decoder* Kit_CreateAudioDecoder(const Kit_Source *src, int stream_index, Kit
goto exit_2;
}
+ // Set format configs
+ Kit_OutputFormat output;
+ memset(&output, 0, sizeof(Kit_OutputFormat));
+ output.samplerate = dec->codec_ctx->sample_rate;
+ output.channels = _FindChannelLayout(dec->codec_ctx->channel_layout);
+ output.bytes = _FindBytes(dec->codec_ctx->sample_fmt);
+ output.is_signed = _FindSignedness(dec->codec_ctx->sample_fmt);
+ output.format = _FindSDLSampleFormat(dec->codec_ctx->sample_fmt);
+
// Create resampler
audio_dec->swr = swr_alloc_set_opts(
NULL,
- _FindAVChannelLayout(format->channels), // Target channel layout
- _FindAVSampleFormat(format->format), // Target fmt
- format->samplerate, // Target samplerate
+ _FindAVChannelLayout(output.channels), // Target channel layout
+ _FindAVSampleFormat(output.format), // Target fmt
+ output.samplerate, // Target samplerate
dec->codec_ctx->channel_layout, // Source channel layout
dec->codec_ctx->sample_fmt, // Source fmt
dec->codec_ctx->sample_rate, // Source samplerate
@@ -222,10 +240,10 @@ Kit_Decoder* Kit_CreateAudioDecoder(const Kit_Source *src, int stream_index, Kit
}
// Set callbacks and userdata, and we're go
- audio_dec->format = format;
dec->dec_decode = dec_decode_audio_cb;
dec->dec_close = dec_close_audio_cb;
dec->userdata = audio_dec;
+ dec->output = output;
return dec;
exit_3:
@@ -247,9 +265,8 @@ int Kit_GetAudioDecoderData(Kit_Decoder *dec, unsigned char *buf, int len) {
}
int ret = 0;
- Kit_AudioDecoder *audio_dec = dec->userdata;
- int bytes_per_sample = audio_dec->format->bytes * audio_dec->format->channels;
- double bytes_per_second = bytes_per_sample * audio_dec->format->samplerate;
+ int bytes_per_sample = dec->output.bytes * dec->output.channels;
+ double bytes_per_second = bytes_per_sample * dec->output.samplerate;
double sync_ts = _GetSystemTime() - dec->clock_sync;
if(packet->pts > sync_ts + AUDIO_SYNC_THRESHOLD) {
diff --git a/src/internal/kitdecoder.c b/src/internal/kitdecoder.c
index 63cbb58..6484e0f 100644
--- a/src/internal/kitdecoder.c
+++ b/src/internal/kitdecoder.c
@@ -13,9 +13,11 @@ static void free_in_video_packet_cb(void *packet) {
}
Kit_Decoder* Kit_CreateDecoder(const Kit_Source *src, int stream_index,
- int out_b_size, dec_free_packet_cb free_out_cb) {
+ int out_b_size, dec_free_packet_cb free_out_cb,
+ int thread_count) {
assert(src != NULL);
assert(out_b_size > 0);
+ assert(thread_count > 0);
AVCodecContext *codec_ctx = NULL;
AVCodec *codec = NULL;
@@ -50,6 +52,10 @@ Kit_Decoder* Kit_CreateDecoder(const Kit_Source *src, int stream_index,
goto exit_1;
}
+ // Set thread count
+ codec_ctx->thread_count = thread_count;
+ codec_ctx->thread_type = FF_THREAD_FRAME;
+
// Open the stream
if(avcodec_open2(codec_ctx, codec, NULL) < 0) {
Kit_SetError("Unable to open codec for stream %d", stream_index);
@@ -93,13 +99,32 @@ exit_0:
return NULL;
}
-int Kit_SetDecoderStreamIndex(Kit_Decoder *dec, int stream_index) {
- if(dec == NULL)
+int Kit_GetDecoderCodecInfo(const Kit_Decoder *dec, Kit_Codec *codec) {
+ if(dec == NULL) {
+ memset(codec, 0, sizeof(Kit_Codec));
return 1;
- dec->stream_index = stream_index;
+ }
+ codec->threads = dec->codec_ctx->thread_count;
+ snprintf(codec->name, KIT_CODEC_NAME_MAX, "%s", dec->codec_ctx->codec->name);
+ snprintf(codec->description, KIT_CODEC_DESC_MAX, "%s", dec->codec_ctx->codec->long_name);
+ return 0;
+}
+
+int Kit_GetDecoderOutputFormat(const Kit_Decoder *dec, Kit_OutputFormat *output) {
+ if(dec == NULL) {
+ memset(output, 0, sizeof(Kit_OutputFormat));
+ return 1;
+ }
+ memcpy(output, &dec->output, sizeof(Kit_OutputFormat));
return 0;
}
+int Kit_GetDecoderStreamIndex(const Kit_Decoder *dec) {
+ if(dec == NULL)
+ return -1;
+ return dec->stream_index;
+}
+
void Kit_SetDecoderClockSync(Kit_Decoder *dec, double sync) {
if(dec == NULL)
return;
diff --git a/src/internal/kitlibstate.c b/src/internal/kitlibstate.c
index d2d98ca..4482ee9 100644
--- a/src/internal/kitlibstate.c
+++ b/src/internal/kitlibstate.c
@@ -1,7 +1,7 @@
#include <stdlib.h>
#include "kitchensink/internal/kitlibstate.h"
-static Kit_LibraryState _librarystate = {0, NULL, NULL};
+static Kit_LibraryState _librarystate = {0, 1, 0, 3, 64, 64, NULL, NULL};
Kit_LibraryState* Kit_GetLibraryState() {
return &_librarystate;
diff --git a/src/internal/subtitle/kitsubtitle.c b/src/internal/subtitle/kitsubtitle.c
index d778903..fa54f43 100644
--- a/src/internal/subtitle/kitsubtitle.c
+++ b/src/internal/subtitle/kitsubtitle.c
@@ -18,10 +18,7 @@
#include "kitchensink/internal/utils/kithelpers.h"
-#define KIT_SUBTITLE_OUT_SIZE 64
-
typedef struct Kit_SubtitleDecoder {
- Kit_SubtitleFormat *format;
Kit_SubtitleRenderer *renderer;
AVSubtitle scratch_frame;
Kit_TextureAtlas *atlas;
@@ -81,31 +78,31 @@ static void dec_close_subtitle_cb(Kit_Decoder *dec) {
free(subtitle_dec);
}
-Kit_Decoder* Kit_CreateSubtitleDecoder(const Kit_Source *src, int stream_index, Kit_SubtitleFormat *format, int video_w, int video_h, int screen_w, int screen_h) {
+Kit_Decoder* Kit_CreateSubtitleDecoder(const Kit_Source *src, int stream_index, int video_w, int video_h, int screen_w, int screen_h) {
assert(src != NULL);
- assert(format != NULL);
+ assert(video_w >= 0);
+ assert(video_h >= 0);
+ assert(screen_w >= 0);
+ assert(screen_h >= 0);
+
if(stream_index < 0) {
return NULL;
}
- Kit_LibraryState *library_state = Kit_GetLibraryState();
+ Kit_LibraryState *state = Kit_GetLibraryState();
// First the generic decoder component
Kit_Decoder *dec = Kit_CreateDecoder(
src,
stream_index,
- KIT_SUBTITLE_OUT_SIZE,
- free_out_subtitle_packet_cb);
+ state->subtitle_buf_frames,
+ free_out_subtitle_packet_cb,
+ state->thread_count);
if(dec == NULL) {
Kit_SetError("Unable to allocate subtitle decoder");
goto exit_0;
}
- // Set format. Note that is_enabled may be changed below ...
- format->is_enabled = true;
- format->stream_index = stream_index;
- format->format = SDL_PIXELFORMAT_RGBA32; // Always this
-
// ... then allocate the subtitle decoder
Kit_SubtitleDecoder *subtitle_dec = calloc(1, sizeof(Kit_SubtitleDecoder));
if(subtitle_dec == NULL) {
@@ -113,8 +110,12 @@ Kit_Decoder* Kit_CreateSubtitleDecoder(const Kit_Source *src, int stream_index,
goto exit_1;
}
+ // Set format. Note that is_enabled may be changed below ...
+ Kit_OutputFormat output;
+ memset(&output, 0, sizeof(Kit_OutputFormat));
+ output.format = SDL_PIXELFORMAT_RGBA32; // Always this
+
// For subtitles, we need a renderer for the stream. Pick one based on codec ID.
- Kit_SubtitleRenderer *ren = NULL;
switch(dec->codec_ctx->codec_id) {
case AV_CODEC_ID_TEXT:
case AV_CODEC_ID_HDMV_TEXT_SUBTITLE:
@@ -122,45 +123,40 @@ Kit_Decoder* Kit_CreateSubtitleDecoder(const Kit_Source *src, int stream_index,
case AV_CODEC_ID_SUBRIP:
case AV_CODEC_ID_SSA:
case AV_CODEC_ID_ASS:
- if(library_state->init_flags & KIT_INIT_ASS) {
- ren = Kit_CreateASSSubtitleRenderer(dec, video_w, video_h, screen_w, screen_h);
- } else {
- format->is_enabled = false;
+ if(state->init_flags & KIT_INIT_ASS) {
+ subtitle_dec->renderer = Kit_CreateASSSubtitleRenderer(dec, video_w, video_h, screen_w, screen_h);
}
break;
case AV_CODEC_ID_DVD_SUBTITLE:
case AV_CODEC_ID_DVB_SUBTITLE:
case AV_CODEC_ID_HDMV_PGS_SUBTITLE:
case AV_CODEC_ID_XSUB:
- ren = Kit_CreateImageSubtitleRenderer(dec, video_w, video_h, screen_w, screen_h);
+ subtitle_dec->renderer = Kit_CreateImageSubtitleRenderer(dec, video_w, video_h, screen_w, screen_h);
break;
default:
- format->is_enabled = false;
break;
}
- if(ren == NULL) {
+ if(subtitle_dec->renderer == NULL) {
Kit_SetError("Unrecognized subtitle format");
goto exit_2;
}
// Allocate texture atlas for subtitle rectangles
- Kit_TextureAtlas *atlas = Kit_CreateAtlas();
- if(atlas == NULL) {
+ subtitle_dec->atlas = Kit_CreateAtlas();
+ if(subtitle_dec->atlas == NULL) {
Kit_SetError("Unable to allocate subtitle texture atlas");
goto exit_3;
}
// Set callbacks and userdata, and we're go
- subtitle_dec->format = format;
- subtitle_dec->renderer = ren;
- subtitle_dec->atlas = atlas;
dec->dec_decode = dec_decode_subtitle_cb;
dec->dec_close = dec_close_subtitle_cb;
dec->userdata = subtitle_dec;
+ dec->output = output;
return dec;
exit_3:
- Kit_CloseSubtitleRenderer(ren);
+ Kit_CloseSubtitleRenderer(subtitle_dec->renderer);
exit_2:
free(subtitle_dec);
exit_1:
diff --git a/src/internal/subtitle/renderers/kitsubass.c b/src/internal/subtitle/renderers/kitsubass.c
index 4115c7d..44205da 100644
--- a/src/internal/subtitle/renderers/kitsubass.c
+++ b/src/internal/subtitle/renderers/kitsubass.c
@@ -170,7 +170,7 @@ Kit_SubtitleRenderer* Kit_CreateASSSubtitleRenderer(Kit_Decoder *dec, int video_
NULL, 1);
ass_set_storage_size(ass_renderer, video_w, video_h);
ass_set_frame_size(ass_renderer, screen_w, screen_h);
- ass_set_hinting(ass_renderer, ASS_HINTING_LIGHT);
+ ass_set_hinting(ass_renderer, state->font_hinting);
// Initialize libass track
ASS_Track *ass_track = ass_new_track(state->libass_handle);
diff --git a/src/internal/video/kitvideo.c b/src/internal/video/kitvideo.c
index e41614b..aaa2a94 100644
--- a/src/internal/video/kitvideo.c
+++ b/src/internal/video/kitvideo.c
@@ -5,17 +5,16 @@
#include <libswscale/swscale.h>
#include "kitchensink/kiterror.h"
+#include "kitchensink/internal/kitlibstate.h"
#include "kitchensink/internal/kitdecoder.h"
#include "kitchensink/internal/utils/kithelpers.h"
#include "kitchensink/internal/utils/kitbuffer.h"
#include "kitchensink/internal/video/kitvideo.h"
#include "kitchensink/internal/utils/kitlog.h"
-#define KIT_VIDEO_OUT_SIZE 2
#define KIT_VIDEO_SYNC_THRESHOLD 0.01
typedef struct Kit_VideoDecoder {
- Kit_VideoFormat *format;
struct SwsContext *sws;
AVFrame *scratch_frame;
} Kit_VideoDecoder;
@@ -33,7 +32,7 @@ static Kit_VideoPacket* _CreateVideoPacket(AVFrame *frame, double pts) {
return p;
}
-static unsigned int _FindPixelFormat(enum AVPixelFormat fmt) {
+static unsigned int _FindSDLPixelFormat(enum AVPixelFormat fmt) {
switch(fmt) {
case AV_PIX_FMT_YUV420P9:
case AV_PIX_FMT_YUV420P10:
@@ -93,7 +92,7 @@ static void dec_decode_video_cb(Kit_Decoder *dec, AVPacket *in_packet) {
out_frame->linesize,
dec->codec_ctx->width,
dec->codec_ctx->height,
- _FindAVPixelFormat(video_dec->format->format),
+ _FindAVPixelFormat(dec->output.format),
1);
// Scale from source format to target format, don't touch the size
@@ -132,30 +131,25 @@ static void dec_close_video_cb(Kit_Decoder *dec) {
free(video_dec);
}
-Kit_Decoder* Kit_CreateVideoDecoder(const Kit_Source *src, int stream_index, Kit_VideoFormat *format) {
+Kit_Decoder* Kit_CreateVideoDecoder(const Kit_Source *src, int stream_index) {
assert(src != NULL);
- assert(format != NULL);
if(stream_index < 0) {
return NULL;
}
+ Kit_LibraryState *state = Kit_GetLibraryState();
+
// First the generic decoder component ...
Kit_Decoder *dec = Kit_CreateDecoder(
src,
stream_index,
- KIT_VIDEO_OUT_SIZE,
- free_out_video_packet_cb);
+ state->video_buf_frames,
+ free_out_video_packet_cb,
+ state->thread_count);
if(dec == NULL) {
goto exit_0;
}
- // Find formats
- format->is_enabled = true;
- format->width = dec->codec_ctx->width;
- format->height = dec->codec_ctx->height;
- format->stream_index = stream_index;
- format->format = _FindPixelFormat(dec->codec_ctx->pix_fmt);
-
// ... then allocate the video decoder
Kit_VideoDecoder *video_dec = calloc(1, sizeof(Kit_VideoDecoder));
if(video_dec == NULL) {
@@ -169,6 +163,13 @@ Kit_Decoder* Kit_CreateVideoDecoder(const Kit_Source *src, int stream_index, Kit
goto exit_2;
}
+ // Set format configs
+ Kit_OutputFormat output;
+ memset(&output, 0, sizeof(Kit_OutputFormat));
+ output.width = dec->codec_ctx->width;
+ output.height = dec->codec_ctx->height;
+ output.format = _FindSDLPixelFormat(dec->codec_ctx->pix_fmt);
+
// Create scaler for handling format changes
video_dec->sws = sws_getContext(
dec->codec_ctx->width, // Source w
@@ -176,7 +177,7 @@ Kit_Decoder* Kit_CreateVideoDecoder(const Kit_Source *src, int stream_index, Kit
dec->codec_ctx->pix_fmt, // Source fmt
dec->codec_ctx->width, // Target w
dec->codec_ctx->height, // Target h
- _FindAVPixelFormat(format->format), // Target fmt
+ _FindAVPixelFormat(output.format), // Target fmt
SWS_BILINEAR,
NULL, NULL, NULL);
if(video_dec->sws == NULL) {
@@ -185,10 +186,10 @@ Kit_Decoder* Kit_CreateVideoDecoder(const Kit_Source *src, int stream_index, Kit
}
// Set callbacks and userdata, and we're go
- video_dec->format = format;
dec->dec_decode = dec_decode_video_cb;
dec->dec_close = dec_close_video_cb;
dec->userdata = video_dec;
+ dec->output = output;
return dec;
exit_3:
@@ -210,7 +211,6 @@ int Kit_GetVideoDecoderData(Kit_Decoder *dec, SDL_Texture *texture) {
return 0;
}
- Kit_VideoDecoder *video_dec = dec->userdata;
double sync_ts = _GetSystemTime() - dec->clock_sync;
// Check if we want the packet
@@ -241,7 +241,7 @@ int Kit_GetVideoDecoderData(Kit_Decoder *dec, SDL_Texture *texture) {
// Update output texture with current video data.
// Take formats into account.
- switch(video_dec->format->format) {
+ switch(dec->output.format) {
case SDL_PIXELFORMAT_YV12:
case SDL_PIXELFORMAT_IYUV:
SDL_UpdateYUVTexture(
diff --git a/src/kitlib.c b/src/kitlib.c
index 0971805..b141208 100644
--- a/src/kitlib.c
+++ b/src/kitlib.c
@@ -9,6 +9,9 @@
static void _libass_msg_callback(int level, const char *fmt, va_list va, void *data) {}
+static int max(int a, int b) { return a > b ? a : b; }
+static int min(int a, int b) { return a < b ? a : b; }
+
int Kit_InitASS(Kit_LibraryState *state) {
#ifdef USE_DYNAMIC_LIBASS
state->ass_so_handle = SDL_LoadObject(DYNAMIC_LIBASS_NAME);
@@ -19,6 +22,11 @@ int Kit_InitASS(Kit_LibraryState *state) {
load_libass(state->ass_so_handle);
#endif
state->libass_handle = ass_library_init();
+ state->thread_count = 1;
+ state->font_hinting = KIT_FONT_HINTING_NONE;
+ state->video_buf_frames = 3;
+ state->audio_buf_frames = 64;
+ state->subtitle_buf_frames = 64;
ass_set_message_cb(state->libass_handle, _libass_msg_callback, NULL);
return 0;
}
@@ -40,9 +48,9 @@ int Kit_Init(unsigned int flags) {
goto exit_0;
}
- #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)
av_register_all();
- #endif
+#endif
if(flags & KIT_INIT_NETWORK) {
avformat_network_init();
@@ -75,6 +83,45 @@ void Kit_Quit() {
state->init_flags = 0;
}
+void Kit_SetHint(Kit_HintType type, int value) {
+ Kit_LibraryState *state = Kit_GetLibraryState();
+ switch(type) {
+ case KIT_HINT_THREAD_COUNT:
+ state->thread_count = max(value, 1);
+ break;
+ case KIT_HINT_FONT_HINTING:
+ state->font_hinting = max(min(value, KIT_FONT_HINTING_COUNT), 0);
+ break;
+ case KIT_HINT_VIDEO_BUFFER_FRAMES:
+ state->video_buf_frames = min(value, 1);
+ break;
+ case KIT_HINT_AUDIO_BUFFER_FRAMES:
+ state->audio_buf_frames = min(value, 1);
+ break;
+ case KIT_HINT_SUBTITLE_BUFFER_FRAMES:
+ state->subtitle_buf_frames = min(value, 1);
+ break;
+ }
+}
+
+int Kit_GetHint(Kit_HintType type) {
+ Kit_LibraryState *state = Kit_GetLibraryState();
+ switch(type) {
+ case KIT_HINT_THREAD_COUNT:
+ return state->thread_count;
+ case KIT_HINT_FONT_HINTING:
+ return state->font_hinting;
+ case KIT_HINT_VIDEO_BUFFER_FRAMES:
+ return state->video_buf_frames;
+ case KIT_HINT_AUDIO_BUFFER_FRAMES:
+ return state->audio_buf_frames;
+ case KIT_HINT_SUBTITLE_BUFFER_FRAMES:
+ return state->subtitle_buf_frames;
+ default:
+ return 0;
+ }
+}
+
void Kit_GetVersion(Kit_Version *version) {
assert(version != NULL);
version->major = KIT_VERSION_MAJOR;
diff --git a/src/kitplayer.c b/src/kitplayer.c
index 192ec21..90381ad 100644
--- a/src/kitplayer.c
+++ b/src/kitplayer.c
@@ -11,26 +11,28 @@
#include "kitchensink/internal/utils/kithelpers.h"
#include "kitchensink/internal/utils/kitlog.h"
+enum DecoderIndex {
+ KIT_VIDEO_DEC = 0,
+ KIT_AUDIO_DEC,
+ KIT_SUBTITLE_DEC,
+ KIT_DEC_COUNT
+};
+
// Return 0 if stream is good but nothing else to do for now
// Return -1 if there may still work to be done
// Return 1 if there was an error or stream end
static int _DemuxStream(const Kit_Player *player) {
assert(player != NULL);
-
AVFormatContext *format_ctx = player->src->format_ctx;
- Kit_Decoder *decoders[] = {
- player->video_dec,
- player->audio_dec,
- player->subtitle_dec
- };
// If any buffer is full, just stop here for now.
// Since we don't know what kind of data is going to come out of av_read_frame, we really
// want to make sure we are prepared for everything :)
- for(int i = 0; i < 3; i++) {
- if(decoders[i] == NULL)
+ for(int i = 0; i < KIT_DEC_COUNT; i++) {
+ Kit_Decoder *dec = player->decoders[i];
+ if(dec == NULL)
continue;
- if(!Kit_CanWriteDecoderInput(decoders[i]))
+ if(!Kit_CanWriteDecoderInput(dec))
return 0;
}
@@ -42,11 +44,12 @@ static int _DemuxStream(const Kit_Player *player) {
}
// Check if this is a packet we need to handle and pass it on
- for(int i = 0; i < 3; i++) {
- if(decoders[i] == NULL)
+ for(int i = 0; i < KIT_DEC_COUNT; i++) {
+ Kit_Decoder *dec = player->decoders[i];
+ if(dec == NULL)
continue;
- if(decoders[i]->stream_index == packet->stream_index) {
- Kit_WriteDecoderInput(decoders[i], packet);
+ if(dec->stream_index == packet->stream_index) {
+ Kit_WriteDecoderInput(player->decoders[i], packet);
return -1;
}
}
@@ -58,15 +61,11 @@ static int _DemuxStream(const Kit_Player *player) {
}
static bool _IsOutputEmpty(const Kit_Player *player) {
- Kit_Decoder *decoders[] = {
- player->video_dec,
- player->audio_dec,
- player->subtitle_dec
- };
- for(int i = 0; i < 3; i++) {
- if(decoders[i] == NULL)
+ for(int i = 0; i < KIT_DEC_COUNT; i++) {
+ Kit_Decoder *dec = player->decoders[i];
+ if(dec == NULL)
continue;
- if(Kit_PeekDecoderOutput(decoders[i]))
+ if(Kit_PeekDecoderOutput(dec))
return false;
}
return true;
@@ -106,9 +105,12 @@ static int _DecoderThread(void *ptr) {
}
// Run decoders for a bit
- while(Kit_RunDecoder(player->video_dec) == 1);
- while(Kit_RunDecoder(player->audio_dec) == 1);
- while(Kit_RunDecoder(player->subtitle_dec) == 1);
+ for(int i = 0; i < KIT_DEC_COUNT; i++) {
+ Kit_Decoder *dec = player->decoders[i];
+ if(dec == NULL)
+ continue;
+ while(Kit_RunDecoder(dec) == 1);
+ }
// Free decoder thread lock.
SDL_UnlockMutex(player->dec_lock);
@@ -132,29 +134,38 @@ Kit_Player* Kit_CreatePlayer(const Kit_Source *src,
int screen_w,
int screen_h) {
assert(src != NULL);
+ assert(screen_w >= 0);
+ assert(screen_h >= 0);
+
+ if(video_stream_index < 0 && subtitle_stream_index >= 0) {
+ Kit_SetError("Subtitle stream selected without video stream");
+ goto exit_0;
+ }
Kit_Player *player = calloc(1, sizeof(Kit_Player));
if(player == NULL) {
Kit_SetError("Unable to allocate player");
- return NULL;
+ goto exit_0;
}
// Initialize audio decoder
- player->audio_dec = Kit_CreateAudioDecoder(src, audio_stream_index, &player->aformat);
- if(player->audio_dec == NULL && audio_stream_index >= 0) {
- goto exit_0;
+ player->decoders[KIT_AUDIO_DEC] = Kit_CreateAudioDecoder(src, audio_stream_index);
+ if(player->decoders[KIT_AUDIO_DEC] == NULL && audio_stream_index >= 0) {
+ goto exit_1;
}
// Initialize video decoder
- player->video_dec = Kit_CreateVideoDecoder(src, video_stream_index, &player->vformat);
- if(player->video_dec == NULL && video_stream_index >= 0) {
- goto exit_1;
+ player->decoders[KIT_VIDEO_DEC] = Kit_CreateVideoDecoder(src, video_stream_index);
+ if(player->decoders[KIT_VIDEO_DEC] == NULL && video_stream_index >= 0) {
+ goto exit_2;
}
- // Initialize subtitle decoder
- player->subtitle_dec = Kit_CreateSubtitleDecoder(
- src, subtitle_stream_index, &player->sformat, player->vformat.width, player->vformat.height, screen_w, screen_h);
- if(player->subtitle_dec == NULL && subtitle_stream_index >= 0) {
+ // Initialize subtitle decoder.
+ Kit_OutputFormat output;
+ Kit_GetDecoderOutputFormat(player->decoders[KIT_VIDEO_DEC], &output);
+ player->decoders[KIT_SUBTITLE_DEC] = Kit_CreateSubtitleDecoder(
+ src, subtitle_stream_index, output.width, output.height, screen_w, screen_h);
+ if(player->decoders[KIT_SUBTITLE_DEC] == NULL && subtitle_stream_index >= 0) {
goto exit_2;
}
@@ -162,29 +173,28 @@ Kit_Player* Kit_CreatePlayer(const Kit_Source *src,
player->dec_lock = SDL_CreateMutex();
if(player->dec_lock == NULL) {
Kit_SetError("Unable to create a decoder thread lock mutex: %s", SDL_GetError());
- goto exit_3;
+ goto exit_2;
}
// Decoder thread
player->dec_thread = SDL_CreateThread(_DecoderThread, "Kit Decoder Thread", player);
if(player->dec_thread == NULL) {
Kit_SetError("Unable to create a decoder thread: %s", SDL_GetError());
- goto exit_4;
+ goto exit_3;
}
player->src = src;
return player;
-exit_4:
- SDL_DestroyMutex(player->dec_lock);
exit_3:
- Kit_CloseDecoder(player->subtitle_dec);
+ SDL_DestroyMutex(player->dec_lock);
exit_2:
- Kit_CloseDecoder(player->video_dec);
+ for(int i = 0; i < KIT_DEC_COUNT; i++) {
+ Kit_CloseDecoder((Kit_Decoder*)player->decoders[i]);
+ }
exit_1:
- Kit_CloseDecoder(player->audio_dec);
-exit_0:
free(player);
+exit_0:
return NULL;
}
@@ -197,9 +207,9 @@ void Kit_ClosePlayer(Kit_Player *player) {
SDL_DestroyMutex(player->dec_lock);
// Shutdown decoders
- Kit_CloseDecoder(player->audio_dec);
- Kit_CloseDecoder(player->video_dec);
- Kit_CloseDecoder(player->subtitle_dec);
+ for(int i = 0; i < KIT_DEC_COUNT; i++) {
+ Kit_CloseDecoder((Kit_Decoder*)player->decoders[i]);
+ }
// Free the player structure itself
free(player);
@@ -207,35 +217,32 @@ void Kit_ClosePlayer(Kit_Player *player) {
void Kit_SetPlayerScreenSize(Kit_Player *player, int w, int h) {
assert(player != NULL);
- if(player->subtitle_dec == NULL)
+ Kit_Decoder *dec = player->decoders[KIT_SUBTITLE_DEC];
+ if(dec == NULL)
return;
- Kit_SetSubtitleDecoderSize(player->subtitle_dec, w, h);
+ Kit_SetSubtitleDecoderSize(dec, w, h);
}
-int Kit_SetPlayerVideoStream(Kit_Player *player, int index) {
+int Kit_GetPlayerVideoStream(const Kit_Player *player) {
assert(player != NULL);
- if(player->video_dec == NULL)
- return 1;
- return Kit_SetDecoderStreamIndex(player->video_dec, index);
+ return Kit_GetDecoderStreamIndex(player->decoders[KIT_VIDEO_DEC]);
}
-int Kit_SetPlayerAudioStream(Kit_Player *player, int index) {
+int Kit_GetPlayerAudioStream(const Kit_Player *player) {
assert(player != NULL);
- if(player->audio_dec == NULL)
- return 1;
- return Kit_SetDecoderStreamIndex(player->audio_dec, index);
+ return Kit_GetDecoderStreamIndex(player->decoders[KIT_AUDIO_DEC]);
}
-int Kit_SetPlayerSubtitleStream(Kit_Player *player, int index) {
+int Kit_GetPlayerSubtitleStream(const Kit_Player *player) {
assert(player != NULL);
- if(player->subtitle_dec == NULL)
- return 1;
- return Kit_SetDecoderStreamIndex(player->subtitle_dec, index);
+ return Kit_GetDecoderStreamIndex(player->decoders[KIT_SUBTITLE_DEC]);
}
int Kit_GetPlayerVideoData(Kit_Player *player, SDL_Texture *texture) {
assert(player != NULL);
- if(player->video_dec == NULL) {
+
+ Kit_Decoder *dec = player->decoders[KIT_VIDEO_DEC];
+ if(dec == NULL) {
return 0;
}
@@ -247,13 +254,15 @@ int Kit_GetPlayerVideoData(Kit_Player *player, SDL_Texture *texture) {
return 0;
}
- return Kit_GetVideoDecoderData(player->video_dec, texture);
+ return Kit_GetVideoDecoderData(dec, texture);
}
int Kit_GetPlayerAudioData(Kit_Player *player, unsigned char *buffer, int length) {
assert(player != NULL);
assert(buffer != NULL);
- if(player->audio_dec == NULL) {
+
+ Kit_Decoder *dec = player->decoders[KIT_AUDIO_DEC];
+ if(dec == NULL) {
return 0;
}
@@ -270,7 +279,7 @@ int Kit_GetPlayerAudioData(Kit_Player *player, unsigned char *buffer, int length
return 0;
}
- return Kit_GetAudioDecoderData(player->audio_dec, buffer, length);
+ return Kit_GetAudioDecoderData(dec, buffer, length);
}
int Kit_GetPlayerSubtitleData(Kit_Player *player, SDL_Texture *texture, SDL_Rect *sources, SDL_Rect *targets, int limit) {
@@ -280,7 +289,8 @@ int Kit_GetPlayerSubtitleData(Kit_Player *player, SDL_Texture *texture, SDL_Rect
assert(targets != NULL);
assert(limit >= 0);
- if(player->subtitle_dec == NULL) {
+ Kit_Decoder *dec = player->decoders[KIT_SUBTITLE_DEC];
+ if(dec == NULL) {
return 0;
}
@@ -292,55 +302,37 @@ int Kit_GetPlayerSubtitleData(Kit_Player *player, SDL_Texture *texture, SDL_Rect
return 0;
}
- return Kit_GetSubtitleDecoderData(player->subtitle_dec, texture, sources, targets, limit);
+ return Kit_GetSubtitleDecoderData(dec, texture, sources, targets, limit);
}
void Kit_GetPlayerInfo(const Kit_Player *player, Kit_PlayerInfo *info) {
assert(player != NULL);
assert(info != NULL);
- Kit_Decoder *audio_dec = player->audio_dec;
- Kit_Decoder *video_dec = player->video_dec;
- Kit_Decoder *subtitle_dec = player->subtitle_dec;
- AVCodecContext *acodec_ctx = audio_dec ? audio_dec->codec_ctx : NULL;
- AVCodecContext *vcodec_ctx = video_dec ? video_dec->codec_ctx : NULL;
- AVCodecContext *scodec_ctx = subtitle_dec ? subtitle_dec->codec_ctx : NULL;
-
- // Reset everything to 0. We might not fill all fields.
- memset(info, 0, sizeof(Kit_PlayerInfo));
-
- if(acodec_ctx != NULL) {
- strncpy(info->acodec, acodec_ctx->codec->name, KIT_CODECMAX-1);
- strncpy(info->acodec_name, acodec_ctx->codec->long_name, KIT_CODECNAMEMAX-1);
- memcpy(&info->audio, &player->aformat, sizeof(Kit_AudioFormat));
- }
- if(vcodec_ctx != NULL) {
- strncpy(info->vcodec, vcodec_ctx->codec->name, KIT_CODECMAX-1);
- strncpy(info->vcodec_name, vcodec_ctx->codec->long_name, KIT_CODECNAMEMAX-1);
- memcpy(&info->video, &player->vformat, sizeof(Kit_VideoFormat));
- }
- if(scodec_ctx != NULL) {
- strncpy(info->scodec, scodec_ctx->codec->name, KIT_CODECMAX-1);
- strncpy(info->scodec_name, scodec_ctx->codec->long_name, KIT_CODECNAMEMAX-1);
- memcpy(&info->subtitle, &player->sformat, sizeof(Kit_SubtitleFormat));
+ void *streams[] = {&info->video, &info->audio, &info->subtitle};
+ for(int i = 0; i < KIT_DEC_COUNT; i++) {
+ Kit_Decoder *dec = player->decoders[i];
+ Kit_PlayerStreamInfo *stream = streams[i];
+ Kit_GetDecoderCodecInfo(dec, &stream->codec);
+ Kit_GetDecoderOutputFormat(dec, &stream->output);
}
}
static void _SetClockSync(Kit_Player *player) {
if(SDL_LockMutex(player->dec_lock) == 0) {
double sync = _GetSystemTime();
- Kit_SetDecoderClockSync(player->video_dec, sync);
- Kit_SetDecoderClockSync(player->audio_dec, sync);
- Kit_SetDecoderClockSync(player->subtitle_dec, sync);
+ for(int i = 0; i < KIT_DEC_COUNT; i++) {
+ Kit_SetDecoderClockSync(player->decoders[i], sync);
+ }
SDL_UnlockMutex(player->dec_lock);
}
}
static void _ChangeClockSync(Kit_Player *player, double delta) {
if(SDL_LockMutex(player->dec_lock) == 0) {
- Kit_ChangeDecoderClockSync(player->video_dec, delta);
- Kit_ChangeDecoderClockSync(player->audio_dec, delta);
- Kit_ChangeDecoderClockSync(player->subtitle_dec, delta);
+ for(int i = 0; i < KIT_DEC_COUNT; i++) {
+ Kit_ChangeDecoderClockSync(player->decoders[i], delta);
+ }
SDL_UnlockMutex(player->dec_lock);
}
}
@@ -416,9 +408,9 @@ int Kit_PlayerSeek(Kit_Player *player, double seek_set) {
return 1;
} else {
_ChangeClockSync(player, position - seek_set);
- Kit_ClearDecoderBuffers(player->video_dec);
- Kit_ClearDecoderBuffers(player->audio_dec);
- Kit_ClearDecoderBuffers(player->subtitle_dec);
+ for(int i = 0; i < KIT_DEC_COUNT; i++) {
+ Kit_ClearDecoderBuffers(player->decoders[i]);
+ }
}
// That's it. Unlock and continue.
@@ -438,11 +430,11 @@ double Kit_GetPlayerDuration(const Kit_Player *player) {
double Kit_GetPlayerPosition(const Kit_Player *player) {
assert(player != NULL);
- if(player->video_dec) {
- return ((Kit_Decoder*)player->video_dec)->clock_pos;
+ if(player->decoders[KIT_VIDEO_DEC]) {
+ return ((Kit_Decoder*)player->decoders[KIT_VIDEO_DEC])->clock_pos;
}
- if(player->audio_dec) {
- return ((Kit_Decoder*)player->audio_dec)->clock_pos;
+ if(player->decoders[KIT_AUDIO_DEC]) {
+ return ((Kit_Decoder*)player->decoders[KIT_AUDIO_DEC])->clock_pos;
}
return 0;
}
diff --git a/src/kitsource.c b/src/kitsource.c
index ef24900..b13cde6 100644
--- a/src/kitsource.c
+++ b/src/kitsource.c
@@ -121,7 +121,7 @@ void Kit_CloseSource(Kit_Source *src) {
free(src);
}
-int Kit_GetSourceStreamInfo(const Kit_Source *src, Kit_StreamInfo *info, int index) {
+int Kit_GetSourceStreamInfo(const Kit_Source *src, Kit_SourceStreamInfo *info, int index) {
assert(src != NULL);
assert(info != NULL);