cog/Plugins/FFMPEG/FFMPEGFileProtocols.m

158 lines
3.8 KiB
Objective-C

//
// FFMPEGFileProtocols.m
// FFMPEG
//
// Created by Christopher Snowhill on 10/4/13.
// Copyright 2013 __NoWork, Inc__. All rights reserved.
//
#include "Plugin.h"
#define __FRAMEWORK__
#import <FFMPEG/avformat.h>
#import <FFMPEG/url.h>
#import <FFMPEG/opt.h>
#undef __FRAMEWORK__
/* standard file protocol */
typedef struct FileContext {
const AVClass *class;
id<CogSource> fd;
} FileContext;
static const AVOption file_options[] = {
{ NULL }
};
#define LIBAVUTIL_VERSION_MAJOR 52
#define LIBAVUTIL_VERSION_MINOR 46
#define LIBAVUTIL_VERSION_MICRO 100
#define AV_VERSION_INT(a, b, c) (a<<16 | b<<8 | c)
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
LIBAVUTIL_VERSION_MINOR, \
LIBAVUTIL_VERSION_MICRO)
static const AVClass file_class = {
.class_name = "file",
.item_name = av_default_item_name,
.option = file_options,
.version = LIBAVUTIL_VERSION_INT,
};
static const AVClass http_class = {
.class_name = "http",
.item_name = av_default_item_name,
.option = file_options,
.version = LIBAVUTIL_VERSION_INT,
};
static const AVClass unpack_class = {
.class_name = "unpack",
.item_name = av_default_item_name,
.option = file_options,
.version = LIBAVUTIL_VERSION_INT,
};
static int file_read(URLContext *h, unsigned char *buf, int size)
{
FileContext *c = h->priv_data;
return [c->fd read:buf amount:size];
}
static int file_check(URLContext *h, int mask)
{
return mask & AVIO_FLAG_READ;
}
static int file_open(URLContext *h, const char *filename, int flags)
{
FileContext *c = h->priv_data;
id<CogSource> fd;
if (flags & AVIO_FLAG_WRITE) {
return -1;
}
NSString * urlString = [NSString stringWithUTF8String:filename];
NSURL * url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
id audioSourceClass = NSClassFromString(@"AudioSource");
fd = [audioSourceClass audioSourceForURL:url];
if (![fd open:url])
return -1;
c->fd = [fd retain];
return 0;
}
static int http_open(URLContext *h, const char *filename, int flags)
{
int rval = file_open( h, filename, flags );
h->is_streamed = 1;
return rval;
}
/* XXX: use llseek */
static int64_t file_seek(URLContext *h, int64_t pos, int whence)
{
FileContext *c = h->priv_data;
return [c->fd seek:pos whence:whence] ? [c->fd tell] : -1;
}
static int64_t http_seek(URLContext *h, int64_t pos, int whence)
{
return -1;
}
static int file_close(URLContext *h)
{
FileContext *c = h->priv_data;
[c->fd release];
return 0;
}
URLProtocol ff_file_protocol = {
.name = "file",
.url_open = file_open,
.url_read = file_read,
.url_seek = file_seek,
.url_close = file_close,
.url_check = file_check,
.priv_data_size = sizeof(FileContext),
.priv_data_class = &file_class,
};
URLProtocol ff_http_protocol = {
.name = "http",
.url_open = http_open,
.url_read = file_read,
.url_seek = http_seek,
.url_close = file_close,
.url_check = file_check,
.priv_data_size = sizeof(FileContext),
.priv_data_class = &file_class,
};
URLProtocol ff_unpack_protocol = {
.name = "unpack",
.url_open = file_open,
.url_read = file_read,
.url_seek = file_seek,
.url_close = file_close,
.url_check = file_check,
.priv_data_size = sizeof(FileContext),
.priv_data_class = &file_class,
};
void registerCogProtocols()
{
ffurl_register_protocol(&ff_file_protocol);
ffurl_register_protocol(&ff_http_protocol);
ffurl_register_protocol(&ff_unpack_protocol);
}