mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
flacdec: add planar output support
Signed-off-by: Mans Rullgard <mans@mansr.com>
This commit is contained in:
parent
e43f56b205
commit
784514a4a8
@ -104,10 +104,21 @@ int avpriv_flac_is_extradata_valid(AVCodecContext *avctx,
|
|||||||
|
|
||||||
static void flac_set_bps(FLACContext *s)
|
static void flac_set_bps(FLACContext *s)
|
||||||
{
|
{
|
||||||
if (s->bps > 16) {
|
enum AVSampleFormat req = s->avctx->request_sample_fmt;
|
||||||
|
int need32 = s->bps > 16;
|
||||||
|
int want32 = av_get_bytes_per_sample(req) > 2;
|
||||||
|
int planar = av_sample_fmt_is_planar(req);
|
||||||
|
|
||||||
|
if (need32 || want32) {
|
||||||
|
if (planar)
|
||||||
|
s->avctx->sample_fmt = AV_SAMPLE_FMT_S32P;
|
||||||
|
else
|
||||||
s->avctx->sample_fmt = AV_SAMPLE_FMT_S32;
|
s->avctx->sample_fmt = AV_SAMPLE_FMT_S32;
|
||||||
s->sample_shift = 32 - s->bps;
|
s->sample_shift = 32 - s->bps;
|
||||||
} else {
|
} else {
|
||||||
|
if (planar)
|
||||||
|
s->avctx->sample_fmt = AV_SAMPLE_FMT_S16P;
|
||||||
|
else
|
||||||
s->avctx->sample_fmt = AV_SAMPLE_FMT_S16;
|
s->avctx->sample_fmt = AV_SAMPLE_FMT_S16;
|
||||||
s->sample_shift = 16 - s->bps;
|
s->sample_shift = 16 - s->bps;
|
||||||
}
|
}
|
||||||
@ -132,7 +143,7 @@ static av_cold int flac_decode_init(AVCodecContext *avctx)
|
|||||||
avpriv_flac_parse_streaminfo(avctx, (FLACStreaminfo *)s, streaminfo);
|
avpriv_flac_parse_streaminfo(avctx, (FLACStreaminfo *)s, streaminfo);
|
||||||
allocate_buffers(s);
|
allocate_buffers(s);
|
||||||
flac_set_bps(s);
|
flac_set_bps(s);
|
||||||
ff_flacdsp_init(&s->dsp, avctx->sample_fmt);
|
ff_flacdsp_init(&s->dsp, avctx->sample_fmt, s->bps);
|
||||||
s->got_streaminfo = 1;
|
s->got_streaminfo = 1;
|
||||||
|
|
||||||
avcodec_get_frame_defaults(&s->frame);
|
avcodec_get_frame_defaults(&s->frame);
|
||||||
@ -233,7 +244,7 @@ static int parse_streaminfo(FLACContext *s, const uint8_t *buf, int buf_size)
|
|||||||
avpriv_flac_parse_streaminfo(s->avctx, (FLACStreaminfo *)s, &buf[8]);
|
avpriv_flac_parse_streaminfo(s->avctx, (FLACStreaminfo *)s, &buf[8]);
|
||||||
allocate_buffers(s);
|
allocate_buffers(s);
|
||||||
flac_set_bps(s);
|
flac_set_bps(s);
|
||||||
ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt);
|
ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt, s->bps);
|
||||||
s->got_streaminfo = 1;
|
s->got_streaminfo = 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -492,9 +503,11 @@ static int decode_frame(FLACContext *s)
|
|||||||
"supported\n");
|
"supported\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
s->bps = s->avctx->bits_per_raw_sample = fi.bps;
|
|
||||||
|
|
||||||
|
if (!s->bps) {
|
||||||
|
s->bps = s->avctx->bits_per_raw_sample = fi.bps;
|
||||||
flac_set_bps(s);
|
flac_set_bps(s);
|
||||||
|
}
|
||||||
|
|
||||||
if (!s->max_blocksize)
|
if (!s->max_blocksize)
|
||||||
s->max_blocksize = FLAC_MAX_BLOCKSIZE;
|
s->max_blocksize = FLAC_MAX_BLOCKSIZE;
|
||||||
@ -520,7 +533,7 @@ static int decode_frame(FLACContext *s)
|
|||||||
|
|
||||||
if (!s->got_streaminfo) {
|
if (!s->got_streaminfo) {
|
||||||
allocate_buffers(s);
|
allocate_buffers(s);
|
||||||
ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt);
|
ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt, s->bps);
|
||||||
s->got_streaminfo = 1;
|
s->got_streaminfo = 1;
|
||||||
dump_headers(s->avctx, (FLACStreaminfo *)s);
|
dump_headers(s->avctx, (FLACStreaminfo *)s);
|
||||||
}
|
}
|
||||||
@ -628,4 +641,9 @@ AVCodec ff_flac_decoder = {
|
|||||||
.decode = flac_decode_frame,
|
.decode = flac_decode_frame,
|
||||||
.capabilities = CODEC_CAP_DR1,
|
.capabilities = CODEC_CAP_DR1,
|
||||||
.long_name = NULL_IF_CONFIG_SMALL("FLAC (Free Lossless Audio Codec)"),
|
.long_name = NULL_IF_CONFIG_SMALL("FLAC (Free Lossless Audio Codec)"),
|
||||||
|
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16,
|
||||||
|
AV_SAMPLE_FMT_S16P,
|
||||||
|
AV_SAMPLE_FMT_S32,
|
||||||
|
AV_SAMPLE_FMT_S32P,
|
||||||
|
-1 },
|
||||||
};
|
};
|
||||||
|
@ -23,10 +23,21 @@
|
|||||||
#include "flacdsp.h"
|
#include "flacdsp.h"
|
||||||
|
|
||||||
#define SAMPLE_SIZE 16
|
#define SAMPLE_SIZE 16
|
||||||
|
#define PLANAR 0
|
||||||
|
#include "flacdsp_template.c"
|
||||||
|
|
||||||
|
#undef PLANAR
|
||||||
|
#define PLANAR 1
|
||||||
#include "flacdsp_template.c"
|
#include "flacdsp_template.c"
|
||||||
|
|
||||||
#undef SAMPLE_SIZE
|
#undef SAMPLE_SIZE
|
||||||
|
#undef PLANAR
|
||||||
#define SAMPLE_SIZE 32
|
#define SAMPLE_SIZE 32
|
||||||
|
#define PLANAR 0
|
||||||
|
#include "flacdsp_template.c"
|
||||||
|
|
||||||
|
#undef PLANAR
|
||||||
|
#define PLANAR 1
|
||||||
#include "flacdsp_template.c"
|
#include "flacdsp_template.c"
|
||||||
|
|
||||||
static void flac_lpc_16_c(int32_t *decoded, const int coeffs[32],
|
static void flac_lpc_16_c(int32_t *decoded, const int coeffs[32],
|
||||||
@ -72,15 +83,27 @@ static void flac_lpc_32_c(int32_t *decoded, const int coeffs[32],
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
av_cold void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt)
|
av_cold void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt,
|
||||||
|
int bps)
|
||||||
{
|
{
|
||||||
|
if (bps > 16)
|
||||||
|
c->lpc = flac_lpc_32_c;
|
||||||
|
else
|
||||||
|
c->lpc = flac_lpc_16_c;
|
||||||
|
|
||||||
switch (fmt) {
|
switch (fmt) {
|
||||||
case AV_SAMPLE_FMT_S32:
|
case AV_SAMPLE_FMT_S32:
|
||||||
c->decorrelate[0] = flac_decorrelate_indep_c_32;
|
c->decorrelate[0] = flac_decorrelate_indep_c_32;
|
||||||
c->decorrelate[1] = flac_decorrelate_ls_c_32;
|
c->decorrelate[1] = flac_decorrelate_ls_c_32;
|
||||||
c->decorrelate[2] = flac_decorrelate_rs_c_32;
|
c->decorrelate[2] = flac_decorrelate_rs_c_32;
|
||||||
c->decorrelate[3] = flac_decorrelate_ms_c_32;
|
c->decorrelate[3] = flac_decorrelate_ms_c_32;
|
||||||
c->lpc = flac_lpc_32_c;
|
break;
|
||||||
|
|
||||||
|
case AV_SAMPLE_FMT_S32P:
|
||||||
|
c->decorrelate[0] = flac_decorrelate_indep_c_32p;
|
||||||
|
c->decorrelate[1] = flac_decorrelate_ls_c_32p;
|
||||||
|
c->decorrelate[2] = flac_decorrelate_rs_c_32p;
|
||||||
|
c->decorrelate[3] = flac_decorrelate_ms_c_32p;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AV_SAMPLE_FMT_S16:
|
case AV_SAMPLE_FMT_S16:
|
||||||
@ -88,7 +111,13 @@ av_cold void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt)
|
|||||||
c->decorrelate[1] = flac_decorrelate_ls_c_16;
|
c->decorrelate[1] = flac_decorrelate_ls_c_16;
|
||||||
c->decorrelate[2] = flac_decorrelate_rs_c_16;
|
c->decorrelate[2] = flac_decorrelate_rs_c_16;
|
||||||
c->decorrelate[3] = flac_decorrelate_ms_c_16;
|
c->decorrelate[3] = flac_decorrelate_ms_c_16;
|
||||||
c->lpc = flac_lpc_16_c;
|
break;
|
||||||
|
|
||||||
|
case AV_SAMPLE_FMT_S16P:
|
||||||
|
c->decorrelate[0] = flac_decorrelate_indep_c_16p;
|
||||||
|
c->decorrelate[1] = flac_decorrelate_ls_c_16p;
|
||||||
|
c->decorrelate[2] = flac_decorrelate_rs_c_16p;
|
||||||
|
c->decorrelate[3] = flac_decorrelate_ms_c_16p;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,6 @@ typedef struct FLACDSPContext {
|
|||||||
int qlevel, int len);
|
int qlevel, int len);
|
||||||
} FLACDSPContext;
|
} FLACDSPContext;
|
||||||
|
|
||||||
void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt);
|
void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt, int bps);
|
||||||
|
|
||||||
#endif /* AVCODEC_FLACDSP_H */
|
#endif /* AVCODEC_FLACDSP_H */
|
||||||
|
@ -19,68 +19,85 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "libavutil/avutil.h"
|
||||||
|
|
||||||
#undef FUNC
|
#undef FUNC
|
||||||
|
#undef FSUF
|
||||||
#undef sample
|
#undef sample
|
||||||
|
#undef sample_type
|
||||||
|
#undef OUT
|
||||||
|
#undef S
|
||||||
|
|
||||||
#if SAMPLE_SIZE == 32
|
#if SAMPLE_SIZE == 32
|
||||||
# define FUNC(n) n ## _32
|
# define sample_type int32_t
|
||||||
# define sample int32_t
|
|
||||||
#else
|
#else
|
||||||
# define FUNC(n) n ## _16
|
# define sample_type int16_t
|
||||||
# define sample int16_t
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if PLANAR
|
||||||
|
# define FSUF AV_JOIN(SAMPLE_SIZE, p)
|
||||||
|
# define sample sample_type *
|
||||||
|
# define OUT(n) n
|
||||||
|
# define S(s, c, i) (s[c][i])
|
||||||
|
#else
|
||||||
|
# define FSUF SAMPLE_SIZE
|
||||||
|
# define sample sample_type
|
||||||
|
# define OUT(n) n[0]
|
||||||
|
# define S(s, c, i) (*s++)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FUNC(n) AV_JOIN(n ## _, FSUF)
|
||||||
|
|
||||||
static void FUNC(flac_decorrelate_indep_c)(uint8_t **out, int32_t **in,
|
static void FUNC(flac_decorrelate_indep_c)(uint8_t **out, int32_t **in,
|
||||||
int channels, int len, int shift)
|
int channels, int len, int shift)
|
||||||
{
|
{
|
||||||
sample *samples = (sample *) out[0];
|
sample *samples = (sample *) OUT(out);
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
for (j = 0; j < len; j++)
|
for (j = 0; j < len; j++)
|
||||||
for (i = 0; i < channels; i++)
|
for (i = 0; i < channels; i++)
|
||||||
*samples++ = in[i][j] << shift;
|
S(samples, i, j) = in[i][j] << shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FUNC(flac_decorrelate_ls_c)(uint8_t **out, int32_t **in,
|
static void FUNC(flac_decorrelate_ls_c)(uint8_t **out, int32_t **in,
|
||||||
int channels, int len, int shift)
|
int channels, int len, int shift)
|
||||||
{
|
{
|
||||||
sample *samples = (sample *) out[0];
|
sample *samples = (sample *) OUT(out);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
int a = in[0][i];
|
int a = in[0][i];
|
||||||
int b = in[1][i];
|
int b = in[1][i];
|
||||||
*samples++ = a << shift;
|
S(samples, 0, i) = a << shift;
|
||||||
*samples++ = (a - b) << shift;
|
S(samples, 1, i) = (a - b) << shift;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FUNC(flac_decorrelate_rs_c)(uint8_t **out, int32_t **in,
|
static void FUNC(flac_decorrelate_rs_c)(uint8_t **out, int32_t **in,
|
||||||
int channels, int len, int shift)
|
int channels, int len, int shift)
|
||||||
{
|
{
|
||||||
sample *samples = (sample *) out[0];
|
sample *samples = (sample *) OUT(out);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
int a = in[0][i];
|
int a = in[0][i];
|
||||||
int b = in[1][i];
|
int b = in[1][i];
|
||||||
*samples++ = (a + b) << shift;
|
S(samples, 0, i) = (a + b) << shift;
|
||||||
*samples++ = b << shift;
|
S(samples, 1, i) = b << shift;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FUNC(flac_decorrelate_ms_c)(uint8_t **out, int32_t **in,
|
static void FUNC(flac_decorrelate_ms_c)(uint8_t **out, int32_t **in,
|
||||||
int channels, int len, int shift)
|
int channels, int len, int shift)
|
||||||
{
|
{
|
||||||
sample *samples = (sample *) out[0];
|
sample *samples = (sample *) OUT(out);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
int a = in[0][i];
|
int a = in[0][i];
|
||||||
int b = in[1][i];
|
int b = in[1][i];
|
||||||
a -= b >> 1;
|
a -= b >> 1;
|
||||||
*samples++ = (a + b) << shift;
|
S(samples, 0, i) = (a + b) << shift;
|
||||||
*samples++ = a << shift;
|
S(samples, 1, i) = a << shift;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user