[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)
|
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:
|
case XCODE_PCM16_HEADER:
|
||||||
settings->wavheader = 1;
|
settings->wavheader = 1;
|
||||||
case XCODE_PCM16_NOHEADER:
|
case XCODE_PCM16_44100:
|
||||||
settings->encode_audio = 1;
|
settings->encode_audio = 1;
|
||||||
settings->format = "s16le";
|
settings->format = "s16le";
|
||||||
settings->audio_codec = AV_CODEC_ID_PCM_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->channel_layout = AV_CH_LAYOUT_STEREO;
|
||||||
settings->channels = 2;
|
settings->channels = 2;
|
||||||
settings->sample_format = AV_SAMPLE_FMT_S16;
|
settings->sample_format = AV_SAMPLE_FMT_S16;
|
||||||
settings->icy = 1;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XCODE_PCM_NATIVE: // Sample rate and bit depth determined by source
|
case XCODE_PCM16_48000:
|
||||||
settings->encode_audio = 1;
|
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->channel_layout = AV_CH_LAYOUT_STEREO;
|
||||||
settings->channels = 2;
|
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;
|
break;
|
||||||
|
|
||||||
case XCODE_MP3:
|
case XCODE_MP3:
|
||||||
|
@ -975,6 +1004,8 @@ open_filter(struct stream_ctx *out_stream, struct stream_ctx *in_stream)
|
||||||
goto out_fail;
|
goto out_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DPRINTF(E_DBG, L_XCODE, "Created 'in' filter: %s\n", args);
|
||||||
|
|
||||||
snprintf(args, sizeof(args),
|
snprintf(args, sizeof(args),
|
||||||
"sample_fmts=%s:sample_rates=%d:channel_layouts=0x%"PRIx64,
|
"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,
|
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;
|
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);
|
ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out", NULL, NULL, filter_graph);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
|
@ -1236,7 +1269,7 @@ transcode_setup(enum transcode_profile profile, enum data_kind data_kind, const
|
||||||
}
|
}
|
||||||
|
|
||||||
struct decode_ctx *
|
struct decode_ctx *
|
||||||
transcode_decode_setup_raw(void)
|
transcode_decode_setup_raw(enum transcode_profile profile)
|
||||||
{
|
{
|
||||||
const AVCodecDescriptor *codec_desc;
|
const AVCodecDescriptor *codec_desc;
|
||||||
struct decode_ctx *ctx;
|
struct decode_ctx *ctx;
|
||||||
|
@ -1245,7 +1278,7 @@ transcode_decode_setup_raw(void)
|
||||||
|
|
||||||
CHECK_NULL(L_XCODE, ctx = calloc(1, sizeof(struct decode_ctx)));
|
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;
|
goto out_free_ctx;
|
||||||
}
|
}
|
||||||
|
@ -1408,6 +1441,9 @@ transcode_encode_cleanup(struct encode_ctx **ctx)
|
||||||
void
|
void
|
||||||
transcode_cleanup(struct transcode_ctx **ctx)
|
transcode_cleanup(struct transcode_ctx **ctx)
|
||||||
{
|
{
|
||||||
|
if (!*ctx)
|
||||||
|
return;
|
||||||
|
|
||||||
transcode_encode_cleanup(&(*ctx)->encode_ctx);
|
transcode_encode_cleanup(&(*ctx)->encode_ctx);
|
||||||
transcode_decode_cleanup(&(*ctx)->decode_ctx);
|
transcode_decode_cleanup(&(*ctx)->decode_ctx);
|
||||||
free(*ctx);
|
free(*ctx);
|
||||||
|
@ -1525,7 +1561,7 @@ transcode(struct evbuffer *evbuf, int *icy_timer, struct transcode_ctx *ctx, int
|
||||||
}
|
}
|
||||||
|
|
||||||
transcode_frame *
|
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;
|
AVFrame *f;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -1537,21 +1573,35 @@ transcode_frame_new(enum transcode_profile profile, void *data, size_t size)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
f->nb_samples = BTOS(size);
|
if (bits_per_sample == 16)
|
||||||
|
{
|
||||||
f->format = AV_SAMPLE_FMT_S16;
|
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;
|
f->channel_layout = AV_CH_LAYOUT_STEREO;
|
||||||
#ifdef HAVE_FFMPEG
|
#ifdef HAVE_FFMPEG
|
||||||
f->channels = 2;
|
f->channels = 2;
|
||||||
#endif
|
#endif
|
||||||
f->pts = AV_NOPTS_VALUE;
|
f->pts = AV_NOPTS_VALUE;
|
||||||
f->sample_rate = 44100;
|
|
||||||
|
|
||||||
// We don't align because the frame won't be given directly to the encoder
|
// 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...?)
|
// anyway, it will first go through the filter (which might align it...?)
|
||||||
ret = avcodec_fill_audio_frame(f, 2, f->format, data, size, 1);
|
ret = avcodec_fill_audio_frame(f, 2, f->format, data, size, 1);
|
||||||
if (ret < 0)
|
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);
|
av_frame_free(&f);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1695,6 +1745,11 @@ transcode_encode_query(struct encode_ctx *ctx, const char *query)
|
||||||
if (ctx->audio_stream.stream)
|
if (ctx->audio_stream.stream)
|
||||||
return av_get_bits_per_sample(ctx->audio_stream.stream->codecpar->codec_id);
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,17 @@
|
||||||
|
|
||||||
enum transcode_profile
|
enum transcode_profile
|
||||||
{
|
{
|
||||||
// Decodes/resamples the best audio stream into 44100 PCM16 (does not add wav header)
|
// Used for errors
|
||||||
XCODE_PCM16_NOHEADER,
|
XCODE_UNKNOWN = 0,
|
||||||
// Decodes/resamples the best audio stream into 44100 PCM16 (with wav header)
|
|
||||||
XCODE_PCM16_HEADER,
|
|
||||||
// Decodes the best audio stream into PCM16 or PCM24, no resampling (does not add wav header)
|
// Decodes the best audio stream into PCM16 or PCM24, no resampling (does not add wav header)
|
||||||
XCODE_PCM_NATIVE,
|
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
|
// Transcodes the best audio stream into MP3
|
||||||
XCODE_MP3,
|
XCODE_MP3,
|
||||||
// Transcodes the best audio stream into OPUS
|
// 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);
|
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 *
|
struct decode_ctx *
|
||||||
transcode_decode_setup_raw(void);
|
transcode_decode_setup_raw(enum transcode_profile profile);
|
||||||
|
|
||||||
int
|
int
|
||||||
transcode_needed(const char *user_agent, const char *client_codecs, char *file_codectype);
|
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
|
* transcode_encode() function. It does not copy, so if you free the data the
|
||||||
* frame will become invalid.
|
* frame will become invalid.
|
||||||
*
|
*
|
||||||
* @in profile Tells the function what kind of frame to create
|
|
||||||
* @in data Buffer with raw data
|
* @in data Buffer with raw data
|
||||||
* @in size Size of buffer
|
* @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
|
* @return Opaque pointer to frame if OK, otherwise NULL
|
||||||
*/
|
*/
|
||||||
transcode_frame *
|
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
|
void
|
||||||
transcode_frame_free(transcode_frame *frame);
|
transcode_frame_free(transcode_frame *frame);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue