summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTuomas Virtanen <katajakasa@gmail.com>2016-01-04 04:33:59 +0200
committerTuomas Virtanen <katajakasa@gmail.com>2016-01-04 04:33:59 +0200
commit537ca31915603d7ed47ab4374a74058e340125c7 (patch)
treeb3c19e8dae778385021ea08be596022d952ccab5 /src
Initial commit; Not done yet though, needs more work.
Diffstat (limited to 'src')
-rw-r--r--src/kitchensink.c26
-rw-r--r--src/kiterror.c30
-rw-r--r--src/kitplayer.c2
-rw-r--r--src/kitsource.c219
4 files changed, 277 insertions, 0 deletions
diff --git a/src/kitchensink.c b/src/kitchensink.c
new file mode 100644
index 0000000..c2b526f
--- /dev/null
+++ b/src/kitchensink.c
@@ -0,0 +1,26 @@
+#include "kitchensink/kitchensink.h"
+#include <libavformat/avformat.h>
+
+static Uint32 _init_flags = 0;
+
+int Kit_Init(Uint32 flags) {
+ if(flags & KIT_INIT_NETWORK)
+ avformat_network_init();
+ if(flags & KIT_INIT_FORMATS)
+ av_register_all();
+ _init_flags = flags;
+ return 0;
+}
+
+void Kit_Quit() {
+ if(_init_flags & KIT_INIT_NETWORK) {
+ avformat_network_deinit();
+ }
+ _init_flags = 0;
+}
+
+void Kit_GetVersion(Kit_Version *version) {
+ version->major = KIT_VERSION_MAJOR;
+ version->minor = KIT_VERSION_MINOR;
+ version->patch = KIT_VERSION_PATCH;
+}
diff --git a/src/kiterror.c b/src/kiterror.c
new file mode 100644
index 0000000..948fda9
--- /dev/null
+++ b/src/kiterror.c
@@ -0,0 +1,30 @@
+#include "kitchensink/kitchensink.h"
+
+#include <stdarg.h>
+#include <stdbool.h>
+
+#define KIT_ERRBUFSIZE 1024
+
+static char _error_available = false;
+static char _error_message[KIT_ERRBUFSIZE] = "\0";
+
+const char* Kit_GetError() {
+ if(_error_available) {
+ _error_available = false;
+ return _error_message;
+ }
+ return NULL;
+}
+
+void Kit_SetError(const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ vsnprintf(_error_message, KIT_ERRBUFSIZE, (char*)fmt, args);
+ va_end(args);
+ _error_available = true;
+}
+
+void Kit_ClearError() {
+ _error_message[0] = 0;
+ _error_available = false;
+}
diff --git a/src/kitplayer.c b/src/kitplayer.c
new file mode 100644
index 0000000..704317f
--- /dev/null
+++ b/src/kitplayer.c
@@ -0,0 +1,2 @@
+#include <kitchensink/kitplayer.h>
+
diff --git a/src/kitsource.c b/src/kitsource.c
new file mode 100644
index 0000000..c947ea1
--- /dev/null
+++ b/src/kitsource.c
@@ -0,0 +1,219 @@
+#include "kitchensink/kitsource.h"
+#include "kitchensink/kiterror.h"
+
+#include <libavcodec/avcodec.h>
+#include <libavformat/avformat.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+Kit_Source* Kit_CreateSourceFromUrl(const char *url) {
+ AVFormatContext *format_ctx = NULL;
+
+ if(url == NULL) {
+ Kit_SetError("Source URL must not be NULL");
+ return NULL;
+ }
+
+ // Attempt to open source
+ if(avformat_open_input(&format_ctx, url, NULL, NULL) < 0) {
+ Kit_SetError("Unable to open source Url");
+ goto exit_0;
+ }
+
+ // Fetch stream information. This may potentially take a while.
+ if(avformat_find_stream_info(format_ctx, NULL) < 0) {
+ Kit_SetError("Unable to fetch source information");
+ goto exit_1;
+ }
+
+ // Find best streams for defaults
+ int best_astream_idx = av_find_best_stream(format_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
+ int best_vstream_idx = av_find_best_stream(format_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
+
+ // Allocate and return a new source
+ // TODO: Check allocation errors
+ Kit_Source *out = calloc(1, sizeof(Kit_Source));
+ out->format_ctx = format_ctx;
+ out->astream_idx = best_astream_idx;
+ out->vstream_idx = best_vstream_idx;
+ return out;
+
+exit_1:
+ avformat_close_input(&format_ctx);
+exit_0:
+ return NULL;
+}
+
+int Kit_InitSourceCodecs(Kit_Source *src) {
+ AVCodecContext *acodec_ctx = NULL;
+ AVCodecContext *vcodec_ctx = NULL;
+ AVCodec *acodec = NULL;
+ AVCodec *vcodec = NULL;
+
+ if(src == NULL) {
+ Kit_SetError("Source must not be NULL");
+ return 1;
+ }
+ if(src->acodec_ctx || src->vcodec_ctx) {
+ Kit_SetError("Source codecs already initialized");
+ return 1;
+ }
+
+ // Make sure indexes seem correct
+ AVFormatContext *format_ctx = (AVFormatContext *)src->format_ctx;
+ if(src->astream_idx < 0 || src->astream_idx >= format_ctx->nb_streams) {
+ Kit_SetError("Invalid audio stream index");
+ return 1;
+ }
+ if(src->vstream_idx < 0 || src->vstream_idx >= format_ctx->nb_streams) {
+ Kit_SetError("Invalid video stream index");
+ return 1;
+ }
+
+ // Find video decoder
+ vcodec = avcodec_find_decoder(format_ctx->streams[src->vstream_idx]->codec->codec_id);
+ if(!vcodec) {
+ Kit_SetError("No suitable video decoder found");
+ goto exit_0;
+ }
+
+ // Copy the original video codec context
+ vcodec_ctx = avcodec_alloc_context3(vcodec);
+ if(avcodec_copy_context(vcodec_ctx, format_ctx->streams[src->vstream_idx]->codec) != 0) {
+ Kit_SetError("Unable to copy video codec context");
+ goto exit_0;
+ }
+
+ // Create a video decoder context
+ if(avcodec_open2(vcodec_ctx, vcodec, NULL) < 0) {
+ Kit_SetError("Unable to allocate video codec context");
+ goto exit_1;
+ }
+
+ // Find audio decoder
+ acodec = avcodec_find_decoder(format_ctx->streams[src->astream_idx]->codec->codec_id);
+ if(!acodec) {
+ Kit_SetError("No suitable audio decoder found");
+ goto exit_2;
+ }
+
+ // Copy the original audio codec context
+ acodec_ctx = avcodec_alloc_context3(acodec);
+ if(avcodec_copy_context(acodec_ctx, format_ctx->streams[src->astream_idx]->codec) != 0) {
+ Kit_SetError("Unable to copy audio codec context");
+ goto exit_2;
+ }
+
+ // Create an audio decoder context
+ if(avcodec_open2(acodec_ctx, acodec, NULL) < 0) {
+ Kit_SetError("Unable to allocate audio codec context");
+ goto exit_3;
+ }
+
+ src->acodec = acodec;
+ src->vcodec = vcodec;
+ src->acodec_ctx = acodec_ctx;
+ src->vcodec_ctx = vcodec_ctx;
+ return 0;
+
+exit_3:
+ avcodec_free_context(&acodec_ctx);
+exit_2:
+ avcodec_close(vcodec_ctx);
+exit_1:
+ avcodec_free_context(&vcodec_ctx);
+exit_0:
+ return 1;
+}
+
+void Kit_CloseSource(Kit_Source *src) {
+ if(src == NULL) return;
+ avcodec_close((AVCodecContext*)src->acodec_ctx);
+ avcodec_close((AVCodecContext*)src->vcodec_ctx);
+ avcodec_free_context((AVCodecContext**)&src->acodec_ctx);
+ avcodec_free_context((AVCodecContext**)&src->vcodec_ctx);
+ avformat_close_input((AVFormatContext **)&src->format_ctx);
+ free(src);
+}
+
+int Kit_GetSourceStreamInfo(const Kit_Source *src, Kit_StreamInfo *info, int index) {
+ if(src == NULL) {
+ Kit_SetError("Source must not be NULL");
+ return 1;
+ }
+ AVFormatContext *format_ctx = (AVFormatContext *)src->format_ctx;
+ if(index < 0 || index >= format_ctx->nb_streams) {
+ Kit_SetError("Invalid stream index");
+ return 1;
+ }
+
+ AVStream *stream = format_ctx->streams[index];
+ switch(stream->codec->codec_type) {
+ case AVMEDIA_TYPE_UNKNOWN: info->type = KIT_STREAMTYPE_UNKNOWN; break;
+ case AVMEDIA_TYPE_DATA: info->type = KIT_STREAMTYPE_DATA; break;
+ case AVMEDIA_TYPE_VIDEO: info->type = KIT_STREAMTYPE_VIDEO; break;
+ case AVMEDIA_TYPE_AUDIO: info->type = KIT_STREAMTYPE_AUDIO; break;
+ case AVMEDIA_TYPE_SUBTITLE: info->type = KIT_STREAMTYPE_SUBTITLE; break;
+ case AVMEDIA_TYPE_ATTACHMENT: info->type = KIT_STREAMTYPE_ATTACHMENT; break;
+ default:
+ Kit_SetError("Unknown native stream type");
+ return 1;
+ }
+
+ info->index = index;
+ info->width = stream->codec->width;
+ info->height = stream->codec->height;
+ return 0;
+}
+
+int Kit_GetBestSourceStream(const Kit_Source *src, const Kit_streamtype type) {
+ if(src == NULL) {
+ Kit_SetError("Source must not be NULL");
+ return -1;
+ }
+ int avmedia_type = 0;
+ switch(type) {
+ case KIT_STREAMTYPE_VIDEO: avmedia_type = AVMEDIA_TYPE_VIDEO; break;
+ case KIT_STREAMTYPE_AUDIO: avmedia_type = AVMEDIA_TYPE_AUDIO; break;
+ default: return -1;
+ }
+ return av_find_best_stream((AVFormatContext *)src->format_ctx, avmedia_type, -1, -1, NULL, 0);
+}
+
+int Kit_SetSourceStream(Kit_Source *src, const Kit_streamtype type, int index) {
+ if(src == NULL) {
+ Kit_SetError("Source must not be NULL");
+ return 1;
+ }
+ switch(type) {
+ case KIT_STREAMTYPE_AUDIO: src->astream_idx = index; break;
+ case KIT_STREAMTYPE_VIDEO: src->vstream_idx = index; break;
+ default:
+ Kit_SetError("Invalid stream type");
+ return 1;
+ }
+ return 0;
+}
+
+int Kit_GetSourceStream(const Kit_Source *src, const Kit_streamtype type) {
+ if(src == NULL) {
+ Kit_SetError("Source must not be NULL");
+ return -1;
+ }
+ switch(type) {
+ case KIT_STREAMTYPE_AUDIO: return src->astream_idx;
+ case KIT_STREAMTYPE_VIDEO: return src->vstream_idx;
+ default:
+ break;
+ }
+ return -1;
+}
+
+int Kit_GetSourceStreamCount(const Kit_Source *src) {
+ if(src == NULL) {
+ Kit_SetError("Source must not be NULL");
+ return -1;
+ }
+ return ((AVFormatContext *)src->format_ctx)->nb_streams;
+}