owntone-server/src/transcode.h

192 lines
5.9 KiB
C

#ifndef __TRANSCODE_H__
#define __TRANSCODE_H__
#include <event2/buffer.h>
#include "db.h"
#include "http.h"
#include "misc.h"
enum transcode_profile
{
// Used for errors
XCODE_UNKNOWN,
// No transcoding, send as-is
XCODE_NONE,
// Decodes the best audio stream into PCM16 or PCM24, no resampling (does not add wav header)
XCODE_PCM_NATIVE,
// Decodes/resamples the best audio stream into PCM16 (with wav header)
XCODE_WAV,
// Decodes/resamples the best audio stream into PCM16/24/32 (no wav headers)
XCODE_PCM16,
XCODE_PCM24,
XCODE_PCM32,
// Transcodes the best audio stream to MP3
XCODE_MP3,
// Transcodes the best audio stream to OPUS
XCODE_OPUS,
// Transcodes the best audio stream to ALAC
XCODE_ALAC,
// Transcodes the best audio stream from OGG
XCODE_OGG,
// Transcodes the best video stream to JPEG/PNG/VP8
XCODE_JPEG,
XCODE_PNG,
XCODE_VP8,
};
enum transcode_seek_type
{
XCODE_SEEK_SIZE,
XCODE_SEEK_SET,
XCODE_SEEK_CUR,
};
typedef void transcode_frame;
typedef int64_t(*transcode_seekfn)(void *arg, int64_t offset, enum transcode_seek_type seek_type);
struct decode_ctx;
struct encode_ctx;
struct transcode_ctx
{
struct decode_ctx *decode_ctx;
struct encode_ctx *encode_ctx;
};
struct transcode_evbuf_io
{
struct evbuffer *evbuf;
// Set to null if no seek support required
transcode_seekfn seekfn;
void *seekfn_arg;
};
struct transcode_metadata_string
{
char *type;
char *codectype;
char *description;
char file_size[64];
char bitrate[32];
};
// 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);
struct encode_ctx *
transcode_encode_setup(enum transcode_profile profile, struct media_quality *quality, struct decode_ctx *src_ctx, int width, int 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);
struct decode_ctx *
transcode_decode_setup_raw(enum transcode_profile profile, struct media_quality *quality);
enum transcode_profile
transcode_needed(const char *user_agent, const char *client_codecs, char *file_codectype);
// Cleaning up
void
transcode_decode_cleanup(struct decode_ctx **ctx);
void
transcode_encode_cleanup(struct encode_ctx **ctx);
void
transcode_cleanup(struct transcode_ctx **ctx);
// Transcoding
/* Demuxes and decodes the next packet from the input.
*
* @out frame A pointer to the frame. Caller should not free it, that will
* be done by the next call to the function or by the cleanup
* function.
* @in ctx Decode context
* @return Positive if OK, negative if error, 0 if EOF
*/
int
transcode_decode(transcode_frame **frame, struct decode_ctx *ctx);
/* Encodes and remuxes a frame. Also resamples if needed.
*
* @out evbuf An evbuffer filled with remuxed data
* @in ctx Encode context
* @in frame The decoded frame to encode, e.g. from transcode_decode
* @in eof If true the muxer will write a trailer to the output
* @return Bytes added if OK, negative if error
*/
int
transcode_encode(struct evbuffer *evbuf, struct encode_ctx *ctx, transcode_frame *frame, int eof);
/* Demuxes, decodes, encodes and remuxes from the input.
*
* @out evbuf An evbuffer filled with remuxed data
* @out icy_timer True if METADATA_ICY_INTERVAL has elapsed
* @in ctx Transcode context
* @in want_bytes Minimum number of bytes the caller wants added to the evbuffer
* - set want_bytes to 0 to transcode everything until EOF/error
* - set want_bytes to 1 to get one encoded packet
* @return Bytes added if OK, negative if error, 0 if EOF
*/
int
transcode(struct evbuffer *evbuf, int *icy_timer, struct transcode_ctx *ctx, int want_bytes);
/* Converts a buffer with raw data to a frame that can be passed directly to the
* transcode_encode() function. It does not copy, so if you free the data the
* frame will become invalid.
*
* @in data Buffer with raw data
* @in size Size of buffer
* @in nsamples Number of samples in the buffer
* @in quality Sample rate, bits per sample and channels
* @return Opaque pointer to frame if OK, otherwise NULL
*/
transcode_frame *
transcode_frame_new(void *data, size_t size, int nsamples, struct media_quality *quality);
void
transcode_frame_free(transcode_frame *frame);
/* Seek to the specified position - next transcode() will return this packet
*
* @in ctx Transcode context
* @in seek Requested seek position in ms
* @return Negative if error, otherwise actual seek position
*/
int
transcode_seek(struct transcode_ctx *ctx, int ms);
/* Query for information about a media file opened by transcode_decode_setup()
*
* @in ctx Decode context
* @in query Query - see implementation for supported queries
* @return Negative if error, otherwise query dependent
*/
int
transcode_decode_query(struct decode_ctx *ctx, const char *query);
/* Query for information (e.g. sample rate) about the output being produced by
* the transcoding
*
* @in ctx Encode context
* @in query Query - see implementation for supported queries
* @return Negative if error, otherwise query dependent
*/
int
transcode_encode_query(struct encode_ctx *ctx, const char *query);
// Metadata
struct http_icy_metadata *
transcode_metadata(struct transcode_ctx *ctx, int *changed);
// When transcoding, we are in essence serving a different source file than the
// original to the client. So we can't serve some of the file metadata from the
// filescanner. This function creates strings to be used for override.
void
transcode_metadata_strings_set(struct transcode_metadata_string *s, enum transcode_profile profile, struct media_quality *q, uint32_t len_ms);
#endif /* !__TRANSCODE_H__ */