mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-26 23:25:56 -05:00
[xcode] Adapt to allow for new raw PCM input profiles, e.g. 48000/16
This commit is contained in:
parent
1696fc3384
commit
ad77a42dbb
@ -187,9 +187,16 @@ init_settings(struct settings_ctx *settings, enum transcode_profile profile)
|
||||
|
||||
switch (profile)
|
||||
{
|
||||
case XCODE_PCM_NATIVE: // Sample rate and bit depth determined by source
|
||||
settings->encode_audio = 1;
|
||||
settings->channel_layout = AV_CH_LAYOUT_STEREO;
|
||||
settings->channels = 2;
|
||||
settings->icy = 1;
|
||||
break;
|
||||
|
||||
case XCODE_PCM16_HEADER:
|
||||
settings->wavheader = 1;
|
||||
case XCODE_PCM16_NOHEADER:
|
||||
case XCODE_PCM16_44100:
|
||||
settings->encode_audio = 1;
|
||||
settings->format = "s16le";
|
||||
settings->audio_codec = AV_CODEC_ID_PCM_S16LE;
|
||||
@ -197,14 +204,36 @@ init_settings(struct settings_ctx *settings, enum transcode_profile profile)
|
||||
settings->channel_layout = AV_CH_LAYOUT_STEREO;
|
||||
settings->channels = 2;
|
||||
settings->sample_format = AV_SAMPLE_FMT_S16;
|
||||
settings->icy = 1;
|
||||
break;
|
||||
|
||||
case XCODE_PCM_NATIVE: // Sample rate and bit depth determined by source
|
||||
case XCODE_PCM16_48000:
|
||||
settings->encode_audio = 1;
|
||||
settings->format = "s16le";
|
||||
settings->audio_codec = AV_CODEC_ID_PCM_S16LE;
|
||||
settings->sample_rate = 48000;
|
||||
settings->channel_layout = AV_CH_LAYOUT_STEREO;
|
||||
settings->channels = 2;
|
||||
settings->icy = 1;
|
||||
settings->sample_format = AV_SAMPLE_FMT_S16;
|
||||
break;
|
||||
|
||||
case XCODE_PCM24_44100:
|
||||
settings->encode_audio = 1;
|
||||
settings->format = "s24le";
|
||||
settings->audio_codec = AV_CODEC_ID_PCM_S24LE;
|
||||
settings->sample_rate = 44100;
|
||||
settings->channel_layout = AV_CH_LAYOUT_STEREO;
|
||||
settings->channels = 2;
|
||||
settings->sample_format = AV_SAMPLE_FMT_S32;
|
||||
break;
|
||||
|
||||
case XCODE_PCM24_48000:
|
||||
settings->encode_audio = 1;
|
||||
settings->format = "s24le";
|
||||
settings->audio_codec = AV_CODEC_ID_PCM_S24LE;
|
||||
settings->sample_rate = 48000;
|
||||
settings->channel_layout = AV_CH_LAYOUT_STEREO;
|
||||
settings->channels = 2;
|
||||
settings->sample_format = AV_SAMPLE_FMT_S32;
|
||||
break;
|
||||
|
||||
case XCODE_MP3:
|
||||
@ -975,6 +1004,8 @@ open_filter(struct stream_ctx *out_stream, struct stream_ctx *in_stream)
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
DPRINTF(E_DBG, L_XCODE, "Created 'in' filter: %s\n", args);
|
||||
|
||||
snprintf(args, sizeof(args),
|
||||
"sample_fmts=%s:sample_rates=%d:channel_layouts=0x%"PRIx64,
|
||||
av_get_sample_fmt_name(out_stream->codec->sample_fmt), out_stream->codec->sample_rate,
|
||||
@ -987,6 +1018,8 @@ open_filter(struct stream_ctx *out_stream, struct stream_ctx *in_stream)
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
DPRINTF(E_DBG, L_XCODE, "Created 'format' filter: %s\n", args);
|
||||
|
||||
ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out", NULL, NULL, filter_graph);
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -1236,7 +1269,7 @@ transcode_setup(enum transcode_profile profile, enum data_kind data_kind, const
|
||||
}
|
||||
|
||||
struct decode_ctx *
|
||||
transcode_decode_setup_raw(void)
|
||||
transcode_decode_setup_raw(enum transcode_profile profile)
|
||||
{
|
||||
const AVCodecDescriptor *codec_desc;
|
||||
struct decode_ctx *ctx;
|
||||
@ -1245,7 +1278,7 @@ transcode_decode_setup_raw(void)
|
||||
|
||||
CHECK_NULL(L_XCODE, ctx = calloc(1, sizeof(struct decode_ctx)));
|
||||
|
||||
if (init_settings(&ctx->settings, XCODE_PCM16_NOHEADER) < 0)
|
||||
if (init_settings(&ctx->settings, profile) < 0)
|
||||
{
|
||||
goto out_free_ctx;
|
||||
}
|
||||
@ -1408,6 +1441,9 @@ transcode_encode_cleanup(struct encode_ctx **ctx)
|
||||
void
|
||||
transcode_cleanup(struct transcode_ctx **ctx)
|
||||
{
|
||||
if (!*ctx)
|
||||
return;
|
||||
|
||||
transcode_encode_cleanup(&(*ctx)->encode_ctx);
|
||||
transcode_decode_cleanup(&(*ctx)->decode_ctx);
|
||||
free(*ctx);
|
||||
@ -1525,7 +1561,7 @@ transcode(struct evbuffer *evbuf, int *icy_timer, struct transcode_ctx *ctx, int
|
||||
}
|
||||
|
||||
transcode_frame *
|
||||
transcode_frame_new(enum transcode_profile profile, void *data, size_t size)
|
||||
transcode_frame_new(void *data, size_t size, int nsamples, int sample_rate, int bits_per_sample)
|
||||
{
|
||||
AVFrame *f;
|
||||
int ret;
|
||||
@ -1537,21 +1573,35 @@ transcode_frame_new(enum transcode_profile profile, void *data, size_t size)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f->nb_samples = BTOS(size);
|
||||
f->format = AV_SAMPLE_FMT_S16;
|
||||
if (bits_per_sample == 16)
|
||||
{
|
||||
f->format = AV_SAMPLE_FMT_S16;
|
||||
}
|
||||
else if (bits_per_sample == 24)
|
||||
{
|
||||
f->format = AV_SAMPLE_FMT_S32;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINTF(E_LOG, L_XCODE, "transcode_frame_new() called with unsupported bps (%d)\n", bits_per_sample);
|
||||
av_frame_free(&f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f->sample_rate = sample_rate;
|
||||
f->nb_samples = nsamples;
|
||||
f->channel_layout = AV_CH_LAYOUT_STEREO;
|
||||
#ifdef HAVE_FFMPEG
|
||||
f->channels = 2;
|
||||
#endif
|
||||
f->pts = AV_NOPTS_VALUE;
|
||||
f->sample_rate = 44100;
|
||||
|
||||
// We don't align because the frame won't be given directly to the encoder
|
||||
// anyway, it will first go through the filter (which might align it...?)
|
||||
ret = avcodec_fill_audio_frame(f, 2, f->format, data, size, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_XCODE, "Error filling frame with rawbuf: %s\n", err2str(ret));
|
||||
DPRINTF(E_LOG, L_XCODE, "Error filling frame with rawbuf, size %zu, samples %d (%d/%d/2): %s\n", size, nsamples, sample_rate, bits_per_sample, err2str(ret));
|
||||
av_frame_free(&f);
|
||||
return NULL;
|
||||
}
|
||||
@ -1695,6 +1745,11 @@ transcode_encode_query(struct encode_ctx *ctx, const char *query)
|
||||
if (ctx->audio_stream.stream)
|
||||
return av_get_bits_per_sample(ctx->audio_stream.stream->codecpar->codec_id);
|
||||
}
|
||||
else if (strcmp(query, "channels") == 0)
|
||||
{
|
||||
if (ctx->audio_stream.stream)
|
||||
return ctx->audio_stream.stream->codecpar->channels;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -8,12 +8,17 @@
|
||||
|
||||
enum transcode_profile
|
||||
{
|
||||
// Decodes/resamples the best audio stream into 44100 PCM16 (does not add wav header)
|
||||
XCODE_PCM16_NOHEADER,
|
||||
// Decodes/resamples the best audio stream into 44100 PCM16 (with wav header)
|
||||
XCODE_PCM16_HEADER,
|
||||
// Used for errors
|
||||
XCODE_UNKNOWN = 0,
|
||||
// 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 44100 PCM16 (with wav header)
|
||||
XCODE_PCM16_HEADER,
|
||||
// Decodes/resamples the best audio stream (no wav headers)
|
||||
XCODE_PCM16_44100,
|
||||
XCODE_PCM16_48000,
|
||||
XCODE_PCM24_44100,
|
||||
XCODE_PCM24_48000,
|
||||
// Transcodes the best audio stream into MP3
|
||||
XCODE_MP3,
|
||||
// Transcodes the best audio stream into OPUS
|
||||
@ -44,7 +49,7 @@ struct transcode_ctx *
|
||||
transcode_setup(enum transcode_profile profile, enum data_kind data_kind, const char *path, uint32_t song_length, off_t *est_size);
|
||||
|
||||
struct decode_ctx *
|
||||
transcode_decode_setup_raw(void);
|
||||
transcode_decode_setup_raw(enum transcode_profile profile);
|
||||
|
||||
int
|
||||
transcode_needed(const char *user_agent, const char *client_codecs, char *file_codectype);
|
||||
@ -100,13 +105,17 @@ transcode(struct evbuffer *evbuf, int *icy_timer, struct transcode_ctx *ctx, int
|
||||
* transcode_encode() function. It does not copy, so if you free the data the
|
||||
* frame will become invalid.
|
||||
*
|
||||
* @in profile Tells the function what kind of frame to create
|
||||
* @in data Buffer with raw data
|
||||
* @in size Size of buffer
|
||||
* @in nsamples Number of samples in the buffer
|
||||
* @in sample_rate
|
||||
* Sample rate
|
||||
* @in bits_per_sample
|
||||
* BPS must be either 16 or 24
|
||||
* @return Opaque pointer to frame if OK, otherwise NULL
|
||||
*/
|
||||
transcode_frame *
|
||||
transcode_frame_new(enum transcode_profile profile, void *data, size_t size);
|
||||
transcode_frame_new(void *data, size_t size, int nsamples, int sample_rate, int bits_per_sample);
|
||||
void
|
||||
transcode_frame_free(transcode_frame *frame);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user