diff options
author | Tuomas Virtanen <katajakasa@gmail.com> | 2018-06-24 23:30:42 +0300 |
---|---|---|
committer | Tuomas Virtanen <katajakasa@gmail.com> | 2018-06-24 23:30:42 +0300 |
commit | d7d5cb75e6fa7f0d2eaeb9cdaf2812dc4c5be466 (patch) | |
tree | 63a68f7fceb4d4a9c06a0e5054375da0477f081f | |
parent | 1d06ec23f264e18a188bf46b72c8794c82c4b89e (diff) |
API rework #36, #37
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); |