[xcode] Change the signature of transcode_setup/transcode_en/decode_setup()

Should make it easier to add/remove parameters without changing all calls to the
functions throughout the code.

Also adds an interface through which to call make_mp4_header().
This commit is contained in:
ejurgensen 2023-12-25 22:29:32 +01:00
parent 9dbec4b99e
commit 4a08644806
12 changed files with 165 additions and 91 deletions

View File

@ -604,6 +604,8 @@ size_calculate(int *dst_w, int *dst_h, int src_w, int src_h, int max_w, int max_
static int
artwork_get(struct evbuffer *evbuf, char *path, struct evbuffer *in_buf, bool is_embedded, enum data_kind data_kind, struct artwork_req_params req_params)
{
struct transcode_decode_setup_args xcode_decode_args = { .profile = XCODE_JPEG }; // Covers XCODE_PNG too
struct transcode_encode_setup_args xcode_encode_args = { 0 };
struct decode_ctx *xcode_decode = NULL;
struct encode_ctx *xcode_encode = NULL;
struct transcode_evbuf_io xcode_evbuf_io = { 0 };
@ -637,13 +639,16 @@ artwork_get(struct evbuffer *evbuf, char *path, struct evbuffer *in_buf, bool is
}
xcode_evbuf_io.evbuf = xcode_buf;
xcode_decode = transcode_decode_setup(XCODE_JPEG, NULL, data_kind, NULL, &xcode_evbuf_io, 0); // Covers XCODE_PNG too
xcode_decode_args.evbuf_io = &xcode_evbuf_io;
xcode_decode_args.is_http = (data_kind == DATA_KIND_HTTP);
}
else
{
xcode_decode = transcode_decode_setup(XCODE_JPEG, NULL, data_kind, path, NULL, 0); // Covers XCODE_PNG too
xcode_decode_args.path = path;
xcode_decode_args.is_http = (data_kind == DATA_KIND_HTTP);
}
xcode_decode = transcode_decode_setup(xcode_decode_args);
if (!xcode_decode)
{
if (path)
@ -702,15 +707,19 @@ artwork_get(struct evbuffer *evbuf, char *path, struct evbuffer *in_buf, bool is
goto out;
}
xcode_encode_args.src_ctx = xcode_decode;
xcode_encode_args.width = dst_width;
xcode_encode_args.height = dst_height;
if (dst_format == ART_FMT_JPEG)
xcode_encode = transcode_encode_setup(XCODE_JPEG, NULL, xcode_decode, dst_width, dst_height);
xcode_encode_args.profile = XCODE_JPEG;
else if (dst_format == ART_FMT_PNG)
xcode_encode = transcode_encode_setup(XCODE_PNG, NULL, xcode_decode, dst_width, dst_height);
xcode_encode_args.profile = XCODE_PNG;
else if (dst_format == ART_FMT_VP8)
xcode_encode = transcode_encode_setup(XCODE_VP8, NULL, xcode_decode, dst_width, dst_height);
xcode_encode_args.profile = XCODE_VP8;
else
xcode_encode = transcode_encode_setup(XCODE_JPEG, NULL, xcode_decode, dst_width, dst_height);
xcode_encode_args.profile = XCODE_JPEG;
xcode_encode = transcode_encode_setup(xcode_encode_args);
if (!xcode_encode)
{
if (path)

View File

@ -673,18 +673,28 @@ static struct stream_ctx *
stream_new_transcode(struct media_file_info *mfi, enum transcode_profile profile, struct httpd_request *hreq,
int64_t offset, int64_t end_offset, event_callback_fn stream_cb)
{
struct transcode_decode_setup_args decode_args = { 0 };
struct transcode_encode_setup_args encode_args = { 0 };
struct media_quality quality = { 0 };
struct stream_ctx *st;
// We use source sample rate etc, but for MP3 we must set a bit rate
quality.bit_rate = 1000 * cfg_getint(cfg_getsec(cfg, "streaming"), "bit_rate");
st = stream_new(mfi, hreq, stream_cb);
if (!st)
{
goto error;
}
// We use source sample rate etc, but for MP3 we must set a bit rate
quality.bit_rate = cfg_getint(cfg_getsec(cfg, "streaming"), "bit_rate");
st->xcode = transcode_setup(profile, &quality, mfi->data_kind, mfi->path, mfi->song_length);
decode_args.profile = profile;
decode_args.is_http = (mfi->data_kind == DATA_KIND_HTTP);
decode_args.path = mfi->path;
decode_args.len_ms = mfi->song_length;
encode_args.profile = profile;
encode_args.quality = &quality;
st->xcode = transcode_setup(decode_args, encode_args);
if (!st->xcode)
{
DPRINTF(E_WARN, L_HTTPD, "Transcoding setup failed, aborting streaming\n");

View File

@ -36,9 +36,11 @@
static int
setup(struct input_source *source)
{
struct transcode_decode_setup_args decode_args = { .profile = XCODE_PCM_NATIVE, .path = source->path, .len_ms = source->len_ms };
struct transcode_encode_setup_args encode_args = { .profile = XCODE_PCM_NATIVE, };
struct transcode_ctx *ctx;
ctx = transcode_setup(XCODE_PCM_NATIVE, NULL, source->data_kind, source->path, source->len_ms);
ctx = transcode_setup(decode_args, encode_args);
if (!ctx)
return -1;

View File

@ -295,6 +295,8 @@ metadata_prepare(struct input_source *source)
static int
setup(struct input_source *source)
{
struct transcode_decode_setup_args decode_args = { .profile = XCODE_PCM_NATIVE, .is_http = true, .len_ms = source->len_ms };
struct transcode_encode_setup_args encode_args = { .profile = XCODE_PCM_NATIVE, };
struct transcode_ctx *ctx;
char *url;
@ -303,8 +305,9 @@ setup(struct input_source *source)
free(source->path);
source->path = url;
decode_args.path = url;
ctx = transcode_setup(XCODE_PCM_NATIVE, NULL, source->data_kind, source->path, source->len_ms);
ctx = transcode_setup(decode_args, encode_args);
if (!ctx)
return -1;

View File

@ -391,21 +391,18 @@ download_seek(void *arg, int64_t offset, enum transcode_seek_type type)
static int
download_xcode_setup(struct download_ctx *download)
{
struct transcode_ctx *xcode;
struct transcode_decode_setup_args decode_args = { .profile = XCODE_OGG, .len_ms = download->len_ms };
struct transcode_encode_setup_args encode_args = { .profile = XCODE_PCM16, };
struct transcode_evbuf_io xcode_evbuf_io = { 0 };
CHECK_NULL(L_SPOTIFY, xcode = malloc(sizeof(struct transcode_ctx)));
struct transcode_ctx *xcode;
xcode_evbuf_io.evbuf = download->read_buf;
xcode_evbuf_io.seekfn = download_seek;
xcode_evbuf_io.seekfn_arg = download;
decode_args.evbuf_io = &xcode_evbuf_io;
xcode->decode_ctx = transcode_decode_setup(XCODE_OGG, NULL, DATA_KIND_SPOTIFY, NULL, &xcode_evbuf_io, download->len_ms);
if (!xcode->decode_ctx)
goto error;
xcode->encode_ctx = transcode_encode_setup(XCODE_PCM16, NULL, xcode->decode_ctx, 0, 0);
if (!xcode->encode_ctx)
xcode = transcode_setup(decode_args, encode_args);
if (!xcode)
goto error;
download->xcode = xcode;

View File

@ -280,8 +280,8 @@ quality_to_xcode(struct media_quality *quality)
static int
encoding_reset(struct media_quality *quality)
{
struct transcode_encode_setup_args encode_args = { 0 };
struct output_quality_subscription *subscription;
struct decode_ctx *decode_ctx;
enum transcode_profile profile;
int i;
@ -293,8 +293,8 @@ encoding_reset(struct media_quality *quality)
return -1;
}
decode_ctx = transcode_decode_setup_raw(profile, quality);
if (!decode_ctx)
encode_args.src_ctx = transcode_decode_setup_raw(profile, quality);
if (!encode_args.src_ctx)
{
DPRINTF(E_LOG, L_PLAYER, "Could not create subscription decoding context (profile %d)\n", profile);
return -1;
@ -309,15 +309,16 @@ encoding_reset(struct media_quality *quality)
if (quality_is_equal(quality, &subscription->quality))
continue; // No resampling required
profile = quality_to_xcode(&subscription->quality);
if (profile != XCODE_UNKNOWN)
subscription->encode_ctx = transcode_encode_setup(profile, &subscription->quality, decode_ctx, 0, 0);
encode_args.profile = quality_to_xcode(&subscription->quality);
encode_args.quality = &subscription->quality;
if (encode_args.profile != XCODE_UNKNOWN)
subscription->encode_ctx = transcode_encode_setup(encode_args);
else
DPRINTF(E_LOG, L_PLAYER, "Could not setup resampling to %d/%d/%d for output\n",
subscription->quality.sample_rate, subscription->quality.bits_per_sample, subscription->quality.channels);
}
transcode_decode_cleanup(&decode_ctx);
transcode_decode_cleanup(&encode_args.src_ctx);
return 0;
}

View File

@ -1120,7 +1120,7 @@ static struct airplay_master_session *
master_session_make(struct media_quality *quality)
{
struct airplay_master_session *rms;
struct decode_ctx *decode_ctx;
struct transcode_encode_setup_args encode_args = { .profile = XCODE_ALAC, .quality = quality };
int ret;
// First check if we already have a suitable session
@ -1146,15 +1146,15 @@ master_session_make(struct media_quality *quality)
goto error;
}
decode_ctx = transcode_decode_setup_raw(XCODE_PCM16, quality);
if (!decode_ctx)
encode_args.src_ctx = transcode_decode_setup_raw(XCODE_PCM16, quality);
if (!encode_args.src_ctx)
{
DPRINTF(E_LOG, L_AIRPLAY, "Could not create decoding context\n");
goto error;
}
rms->encode_ctx = transcode_encode_setup(XCODE_ALAC, quality, decode_ctx, 0, 0);
transcode_decode_cleanup(&decode_ctx);
rms->encode_ctx = transcode_encode_setup(encode_args);
transcode_decode_cleanup(&encode_args.src_ctx);
if (!rms->encode_ctx)
{
DPRINTF(E_LOG, L_AIRPLAY, "Will not be able to stream AirPlay 2, ffmpeg has no ALAC encoder\n");

View File

@ -2362,7 +2362,7 @@ cast_metadata_send(struct output_metadata *metadata)
static int
cast_init(void)
{
struct decode_ctx *decode_ctx;
struct transcode_encode_setup_args encode_args = { .profile = XCODE_OPUS, .quality = &cast_quality_default };
int i;
int ret;
@ -2386,15 +2386,15 @@ cast_init(void)
return -1;
}
decode_ctx = transcode_decode_setup_raw(XCODE_PCM16, &cast_quality_default);
if (!decode_ctx)
encode_args.src_ctx = transcode_decode_setup_raw(XCODE_PCM16, &cast_quality_default);
if (!encode_args.src_ctx)
{
DPRINTF(E_LOG, L_CAST, "Could not create decoding context\n");
goto out_tls_deinit;
}
cast_encode_ctx = transcode_encode_setup(XCODE_OPUS, &cast_quality_default, decode_ctx, 0, 0);
transcode_decode_cleanup(&decode_ctx);
cast_encode_ctx = transcode_encode_setup(encode_args);
transcode_decode_cleanup(&encode_args.src_ctx);
if (!cast_encode_ctx)
{
DPRINTF(E_LOG, L_CAST, "Will not be able to stream Chromecast, libav does not support Opus encoding\n");

View File

@ -1855,7 +1855,7 @@ static struct raop_master_session *
master_session_make(struct media_quality *quality, bool encrypt)
{
struct raop_master_session *rms;
struct decode_ctx *decode_ctx;
struct transcode_encode_setup_args encode_args = { .profile = XCODE_ALAC, .quality = quality };
int ret;
// First check if we already have a suitable session
@ -1883,15 +1883,15 @@ master_session_make(struct media_quality *quality, bool encrypt)
return NULL;
}
decode_ctx = transcode_decode_setup_raw(XCODE_PCM16, quality);
if (!decode_ctx)
encode_args.src_ctx = transcode_decode_setup_raw(XCODE_PCM16, quality);
if (!encode_args.src_ctx)
{
DPRINTF(E_LOG, L_RAOP, "Could not create decoding context\n");
goto error;
}
rms->encode_ctx = transcode_encode_setup(XCODE_ALAC, quality, decode_ctx, 0, 0);
transcode_decode_cleanup(&decode_ctx);
rms->encode_ctx = transcode_encode_setup(encode_args);
transcode_decode_cleanup(&encode_args.src_ctx);
if (!rms->encode_ctx)
{
DPRINTF(E_LOG, L_RAOP, "Will not be able to stream AirPlay 2, ffmpeg has no ALAC encoder\n");

View File

@ -115,17 +115,17 @@ extern struct event_base *evbase_player;
static struct encode_ctx *
encoder_setup(enum player_format format, struct media_quality *quality)
{
struct decode_ctx *decode_ctx = NULL;
struct transcode_encode_setup_args encode_args = { .profile = XCODE_MP3, .quality = quality };
struct encode_ctx *encode_ctx = NULL;
if (quality->bits_per_sample == 16)
decode_ctx = transcode_decode_setup_raw(XCODE_PCM16, quality);
encode_args.src_ctx = transcode_decode_setup_raw(XCODE_PCM16, quality);
else if (quality->bits_per_sample == 24)
decode_ctx = transcode_decode_setup_raw(XCODE_PCM24, quality);
encode_args.src_ctx = transcode_decode_setup_raw(XCODE_PCM24, quality);
else if (quality->bits_per_sample == 32)
decode_ctx = transcode_decode_setup_raw(XCODE_PCM32, quality);
encode_args.src_ctx = transcode_decode_setup_raw(XCODE_PCM32, quality);
if (!decode_ctx)
if (!encode_args.src_ctx)
{
DPRINTF(E_LOG, L_STREAMING, "Error setting up decoder for quality sr %d, bps %d, ch %d, cannot encode\n",
quality->sample_rate, quality->bits_per_sample, quality->channels);
@ -133,7 +133,7 @@ encoder_setup(enum player_format format, struct media_quality *quality)
}
if (format == PLAYER_FORMAT_MP3)
encode_ctx = transcode_encode_setup(XCODE_MP3, quality, decode_ctx, 0, 0);
encode_ctx = transcode_encode_setup(encode_args);
if (!encode_ctx)
{
@ -143,7 +143,7 @@ encoder_setup(enum player_format format, struct media_quality *quality)
}
out:
transcode_decode_cleanup(&decode_ctx);
transcode_decode_cleanup(&encode_args.src_ctx);
return encode_ctx;
}

View File

@ -38,7 +38,6 @@
#include "logger.h"
#include "conffile.h"
#include "db.h"
#include "misc.h"
#include "transcode.h"
@ -151,8 +150,8 @@ struct decode_ctx
// Source duration in ms as provided by caller
uint32_t len_ms;
// Data kind (used to determine if ICY metadata is relevant to look for)
enum data_kind data_kind;
// Used to determine if ICY metadata is relevant to look for
bool is_http;
// Set to true if we just seeked
bool resume;
@ -1202,6 +1201,8 @@ mp4_header_trailer_from_evbuf(uint8_t **header, size_t *header_len, uint8_t **tr
static int
make_mp4_header(struct evbuffer **mp4_header, const char *url)
{
struct transcode_decode_setup_args decode_args = { .profile = XCODE_MP4_ALAC_HEADER };
struct transcode_encode_setup_args encode_args = { .profile = XCODE_MP4_ALAC_HEADER };
struct transcode_ctx ctx = { 0 };
struct transcode_evbuf_io evbuf_io = { 0 };
uint8_t free_tag[4] = { 'f', 'r', 'e', 'e' };
@ -1220,11 +1221,14 @@ make_mp4_header(struct evbuffer **mp4_header, const char *url)
evbuf_io.seekfn = dummy_seek;
evbuf_io.seekfn_arg = &ctx;
ctx.decode_ctx = transcode_decode_setup(XCODE_MP4_ALAC_HEADER, NULL, DATA_KIND_FILE, url, NULL, -1);
decode_args.path = url;
ctx.decode_ctx = transcode_decode_setup(decode_args);
if (!ctx.decode_ctx)
goto error;
ctx.encode_ctx = transcode_encode_setup_with_io(XCODE_MP4_ALAC_HEADER, NULL, &evbuf_io, ctx.decode_ctx, 0, 0);
encode_args.evbuf_io = &evbuf_io;
encode_args.src_ctx = ctx.decode_ctx;
ctx.encode_ctx = transcode_encode_setup(encode_args);
if (!ctx.encode_ctx)
goto error;
@ -1394,7 +1398,7 @@ open_input(struct decode_ctx *ctx, const char *path, struct transcode_evbuf_io *
ctx->ifmt_ctx->format_probesize = 65536;
}
if (ctx->data_kind == DATA_KIND_HTTP)
if (ctx->is_http)
{
av_dict_set(&options, "icy", "1", 0);
@ -1501,7 +1505,7 @@ close_output(struct encode_ctx *ctx)
}
static int
open_output(struct encode_ctx *ctx, struct transcode_evbuf_io *evbuf_io, struct decode_ctx *src_ctx)
open_output(struct encode_ctx *ctx, struct transcode_evbuf_io *evbuf_io, struct evbuffer *prepared_header, struct decode_ctx *src_ctx)
{
#if USE_CONST_AVFORMAT
const AVOutputFormat *oformat;
@ -1584,7 +1588,12 @@ open_output(struct encode_ctx *ctx, struct transcode_evbuf_io *evbuf_io, struct
evbuffer_add_buffer(ctx->obuf, header);
evbuffer_free(header);
}
if (ctx->settings.with_mp4_header)
if (ctx->settings.with_mp4_header && prepared_header)
{
evbuffer_add_buffer(ctx->obuf, prepared_header);
}
else if (ctx->settings.with_mp4_header)
{
ret = make_mp4_header(&header, src_ctx->ifmt_ctx->url);
if (ret < 0)
@ -1915,7 +1924,7 @@ open_filters(struct encode_ctx *ctx, struct decode_ctx *src_ctx)
/* Setup */
struct decode_ctx *
transcode_decode_setup(enum transcode_profile profile, struct media_quality *quality, enum data_kind data_kind, const char *path, struct transcode_evbuf_io *evbuf_io, uint32_t len_ms)
transcode_decode_setup(struct transcode_decode_setup_args args)
{
struct decode_ctx *ctx;
int ret;
@ -1924,23 +1933,24 @@ transcode_decode_setup(enum transcode_profile profile, struct media_quality *qua
CHECK_NULL(L_XCODE, ctx->decoded_frame = av_frame_alloc());
CHECK_NULL(L_XCODE, ctx->packet = av_packet_alloc());
ctx->len_ms = len_ms;
ctx->data_kind = data_kind;
ctx->len_ms = args.len_ms;
ret = init_settings(&ctx->settings, profile, quality);
ret = init_settings(&ctx->settings, args.profile, args.quality);
if (ret < 0)
goto fail_free;
if (data_kind == DATA_KIND_HTTP)
if (args.is_http)
{
ret = open_input(ctx, path, evbuf_io, PROBE_TYPE_QUICK);
ctx->is_http = true;
ret = open_input(ctx, args.path, args.evbuf_io, PROBE_TYPE_QUICK);
// Retry with a default, slower probe size
if (ret == AVERROR_STREAM_NOT_FOUND)
ret = open_input(ctx, path, evbuf_io, PROBE_TYPE_DEFAULT);
ret = open_input(ctx, args.path, args.evbuf_io, PROBE_TYPE_DEFAULT);
}
else
ret = open_input(ctx, path, evbuf_io, PROBE_TYPE_DEFAULT);
ret = open_input(ctx, args.path, args.evbuf_io, PROBE_TYPE_DEFAULT);
if (ret < 0)
goto fail_free;
@ -1955,7 +1965,7 @@ transcode_decode_setup(enum transcode_profile profile, struct media_quality *qua
}
struct encode_ctx *
transcode_encode_setup_with_io(enum transcode_profile profile, struct media_quality *quality, struct transcode_evbuf_io *evbuf_io, struct decode_ctx *src_ctx, int width, int height)
transcode_encode_setup(struct transcode_encode_setup_args args)
{
struct encode_ctx *ctx;
int dst_bytes_per_sample;
@ -1966,29 +1976,29 @@ transcode_encode_setup_with_io(enum transcode_profile profile, struct media_qual
CHECK_NULL(L_XCODE, ctx->evbuf_io.evbuf = evbuffer_new());
// Caller didn't specify one, so use our own
if (!evbuf_io)
evbuf_io = &ctx->evbuf_io;
if (!args.evbuf_io)
args.evbuf_io = &ctx->evbuf_io;
// Initialize general settings
if (init_settings(&ctx->settings, profile, quality) < 0)
if (init_settings(&ctx->settings, args.profile, args.quality) < 0)
goto error;
if (ctx->settings.encode_audio && init_settings_from_audio(&ctx->settings, profile, src_ctx, quality) < 0)
if (ctx->settings.encode_audio && init_settings_from_audio(&ctx->settings, args.profile, args.src_ctx, args.quality) < 0)
goto error;
if (ctx->settings.encode_video && init_settings_from_video(&ctx->settings, profile, src_ctx, width, height) < 0)
if (ctx->settings.encode_video && init_settings_from_video(&ctx->settings, args.profile, args.src_ctx, args.width, args.height) < 0)
goto error;
dst_bytes_per_sample = av_get_bytes_per_sample(ctx->settings.sample_format);
ctx->bytes_total = size_estimate(profile, ctx->settings.bit_rate, ctx->settings.sample_rate, dst_bytes_per_sample, ctx->settings.nb_channels, src_ctx->len_ms);
ctx->bytes_total = size_estimate(args.profile, ctx->settings.bit_rate, ctx->settings.sample_rate, dst_bytes_per_sample, ctx->settings.nb_channels, args.src_ctx->len_ms);
if (ctx->settings.with_icy && src_ctx->data_kind == DATA_KIND_HTTP)
if (ctx->settings.with_icy && args.src_ctx->is_http)
ctx->icy_interval = METADATA_ICY_INTERVAL * ctx->settings.nb_channels * dst_bytes_per_sample * ctx->settings.sample_rate;
if (open_output(ctx, evbuf_io, src_ctx) < 0)
if (open_output(ctx, args.evbuf_io, args.prepared_header, args.src_ctx) < 0)
goto error;
if (open_filters(ctx, src_ctx) < 0)
if (open_filters(ctx, args.src_ctx) < 0)
goto error;
return ctx;
@ -1998,27 +2008,22 @@ transcode_encode_setup_with_io(enum transcode_profile profile, struct media_qual
return NULL;
}
struct encode_ctx *
transcode_encode_setup(enum transcode_profile profile, struct media_quality *quality, struct decode_ctx *src_ctx, int width, int height)
{
return transcode_encode_setup_with_io(profile, quality, NULL, src_ctx, width, height);
}
struct transcode_ctx *
transcode_setup(enum transcode_profile profile, struct media_quality *quality, enum data_kind data_kind, const char *path, uint32_t len_ms)
transcode_setup(struct transcode_decode_setup_args decode_args, struct transcode_encode_setup_args encode_args)
{
struct transcode_ctx *ctx;
CHECK_NULL(L_XCODE, ctx = calloc(1, sizeof(struct transcode_ctx)));
ctx->decode_ctx = transcode_decode_setup(profile, quality, data_kind, path, NULL, len_ms);
ctx->decode_ctx = transcode_decode_setup(decode_args);
if (!ctx->decode_ctx)
{
free(ctx);
return NULL;
}
ctx->encode_ctx = transcode_encode_setup(profile, quality, ctx->decode_ctx, 0, 0);
encode_args.src_ctx = ctx->decode_ctx;
ctx->encode_ctx = transcode_encode_setup(encode_args);
if (!ctx->encode_ctx)
{
transcode_decode_cleanup(&ctx->decode_ctx);
@ -2618,3 +2623,20 @@ transcode_metadata_strings_set(struct transcode_metadata_string *s, enum transco
DPRINTF(E_WARN, L_XCODE, "transcode_metadata_strings_set() called with unknown profile %d\n", profile);
}
}
int
transcode_create_header(struct evbuffer **header, enum transcode_profile profile, const char *path)
{
int ret;
switch (profile)
{
case XCODE_MP4_ALAC:
ret = make_mp4_header(header, path);
break;
default:
ret = -1;
}
return ret;
}

View File

@ -3,7 +3,6 @@
#define __TRANSCODE_H__
#include <event2/buffer.h>
#include "db.h"
#include "http.h"
#include "misc.h"
@ -66,6 +65,29 @@ struct transcode_evbuf_io
void *seekfn_arg;
};
struct transcode_decode_setup_args
{
enum transcode_profile profile;
struct media_quality *quality;
bool is_http;
uint32_t len_ms;
// Source must be either of these
const char *path;
struct transcode_evbuf_io *evbuf_io;
};
struct transcode_encode_setup_args
{
enum transcode_profile profile;
struct media_quality *quality;
struct decode_ctx *src_ctx;
struct transcode_evbuf_io *evbuf_io;
struct evbuffer *prepared_header;
int width;
int height;
};
struct transcode_metadata_string
{
char *type;
@ -78,16 +100,13 @@ struct transcode_metadata_string
// Setting up
struct decode_ctx *
transcode_decode_setup(enum transcode_profile profile, struct media_quality *quality, enum data_kind data_kind, const char *path, struct transcode_evbuf_io *evbuf_io, uint32_t len_ms);
transcode_decode_setup(struct transcode_decode_setup_args args);
struct encode_ctx *
transcode_encode_setup(enum transcode_profile profile, struct media_quality *quality, struct decode_ctx *src_ctx, int width, int height);
struct encode_ctx *
transcode_encode_setup_with_io(enum transcode_profile profile, struct media_quality *quality, struct transcode_evbuf_io *evbuf_io, struct decode_ctx *src_ctx, int width, int height);
transcode_encode_setup(struct transcode_encode_setup_args args);
struct transcode_ctx *
transcode_setup(enum transcode_profile profile, struct media_quality *quality, enum data_kind data_kind, const char *path, uint32_t len_ms);
transcode_setup(struct transcode_decode_setup_args decode_args, struct transcode_encode_setup_args encode_args);
struct decode_ctx *
transcode_decode_setup_raw(enum transcode_profile profile, struct media_quality *quality);
@ -201,4 +220,15 @@ transcode_metadata(struct transcode_ctx *ctx, int *changed);
void
transcode_metadata_strings_set(struct transcode_metadata_string *s, enum transcode_profile profile, struct media_quality *q, uint32_t len_ms);
/* Creates a header for later transcoding of a source file. This header can be
* given to transcode_encode_setup which in some cases will make it faster (MP4)
*
* @out header An evbuffer with the header
* @in profile Transcoding profile
* @in path Path to the source file
* @return Negative if error, otherwise zero
*/
int
transcode_prepare_header(struct evbuffer **header, enum transcode_profile profile, const char *path);
#endif /* !__TRANSCODE_H__ */