Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
F
ffmpeg.wasm-core
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Linshizhi
ffmpeg.wasm-core
Commits
5e1bbb8c
Commit
5e1bbb8c
authored
Dec 04, 2012
by
Justin Ruggles
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
alacenc: add support for multi-channel encoding
parent
b519298a
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
177 additions
and
80 deletions
+177
-80
Changelog
Changelog
+1
-0
Makefile
libavcodec/Makefile
+2
-2
alac.c
libavcodec/alac.c
+6
-40
alac_data.c
libavcodec/alac_data.c
+56
-0
alac_data.h
libavcodec/alac_data.h
+46
-0
alacenc.c
libavcodec/alacenc.c
+66
-38
No files found.
Changelog
View file @
5e1bbb8c
...
...
@@ -5,6 +5,7 @@ version <next>:
- ashowinfo audio filter
- 24-bit FLAC encoding
- audio volume filter
- multi-channel ALAC encoding up to 7.1
version 9_beta2:
...
...
libavcodec/Makefile
View file @
5e1bbb8c
...
...
@@ -85,8 +85,8 @@ OBJS-$(CONFIG_AC3_DECODER) += ac3dec.o ac3dec_data.o ac3.o kbdwin.o
OBJS-$(CONFIG_AC3_ENCODER)
+=
ac3enc_float.o
ac3enc.o
ac3tab.o
\
ac3.o
kbdwin.o
OBJS-$(CONFIG_AC3_FIXED_ENCODER)
+=
ac3enc_fixed.o
ac3enc.o
ac3tab.o
ac3.o
OBJS-$(CONFIG_ALAC_DECODER)
+=
alac.o
OBJS-$(CONFIG_ALAC_ENCODER)
+=
alacenc.o
OBJS-$(CONFIG_ALAC_DECODER)
+=
alac.o
alac_data.o
OBJS-$(CONFIG_ALAC_ENCODER)
+=
alacenc.o
alac_data.o
OBJS-$(CONFIG_ALS_DECODER)
+=
alsdec.o
bgmc.o
mpeg4audio.o
OBJS-$(CONFIG_AMRNB_DECODER)
+=
amrnbdec.o
celp_filters.o
\
celp_math.o
acelp_filters.o
\
...
...
libavcodec/alac.c
View file @
5e1bbb8c
...
...
@@ -52,9 +52,9 @@
#include "internal.h"
#include "unary.h"
#include "mathops.h"
#include "alac_data.h"
#define ALAC_EXTRADATA_SIZE 36
#define MAX_CHANNELS 8
typedef
struct
{
AVCodecContext
*
avctx
;
...
...
@@ -76,40 +76,6 @@ typedef struct {
int
nb_samples
;
/**< number of samples in the current frame */
}
ALACContext
;
enum
RawDataBlockType
{
/* At the moment, only SCE, CPE, LFE, and END are recognized. */
TYPE_SCE
,
TYPE_CPE
,
TYPE_CCE
,
TYPE_LFE
,
TYPE_DSE
,
TYPE_PCE
,
TYPE_FIL
,
TYPE_END
};
static
const
uint8_t
alac_channel_layout_offsets
[
8
][
8
]
=
{
{
0
},
{
0
,
1
},
{
2
,
0
,
1
},
{
2
,
0
,
1
,
3
},
{
2
,
0
,
1
,
3
,
4
},
{
2
,
0
,
1
,
4
,
5
,
3
},
{
2
,
0
,
1
,
4
,
5
,
6
,
3
},
{
2
,
6
,
7
,
0
,
1
,
4
,
5
,
3
}
};
static
const
uint16_t
alac_channel_layouts
[
8
]
=
{
AV_CH_LAYOUT_MONO
,
AV_CH_LAYOUT_STEREO
,
AV_CH_LAYOUT_SURROUND
,
AV_CH_LAYOUT_4POINT0
,
AV_CH_LAYOUT_5POINT0_BACK
,
AV_CH_LAYOUT_5POINT1_BACK
,
AV_CH_LAYOUT_6POINT1_BACK
,
AV_CH_LAYOUT_7POINT1_WIDE_BACK
};
static
inline
unsigned
int
decode_scalar
(
GetBitContext
*
gb
,
int
k
,
int
bps
)
{
unsigned
int
x
=
get_unary_0_9
(
gb
);
...
...
@@ -431,7 +397,7 @@ static int alac_decode_frame(AVCodecContext *avctx, void *data,
int
*
got_frame_ptr
,
AVPacket
*
avpkt
)
{
ALACContext
*
alac
=
avctx
->
priv_data
;
enum
RawDataBlockType
element
;
enum
Alac
RawDataBlockType
element
;
int
channels
;
int
ch
,
ret
,
got_end
;
...
...
@@ -458,7 +424,7 @@ static int alac_decode_frame(AVCodecContext *avctx, void *data,
}
ret
=
decode_element
(
avctx
,
data
,
alac_channel_layout_offsets
[
alac
->
channels
-
1
][
ch
],
ff_
alac_channel_layout_offsets
[
alac
->
channels
-
1
][
ch
],
channels
);
if
(
ret
<
0
&&
get_bits_left
(
&
alac
->
gb
))
return
ret
;
...
...
@@ -581,17 +547,17 @@ static av_cold int alac_decode_init(AVCodecContext * avctx)
av_log
(
avctx
,
AV_LOG_WARNING
,
"Invalid channel count
\n
"
);
alac
->
channels
=
avctx
->
channels
;
}
else
{
if
(
alac
->
channels
>
MAX_CHANNELS
)
if
(
alac
->
channels
>
ALAC_
MAX_CHANNELS
)
alac
->
channels
=
avctx
->
channels
;
else
avctx
->
channels
=
alac
->
channels
;
}
if
(
avctx
->
channels
>
MAX_CHANNELS
)
{
if
(
avctx
->
channels
>
ALAC_
MAX_CHANNELS
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Unsupported channel count: %d
\n
"
,
avctx
->
channels
);
return
AVERROR_PATCHWELCOME
;
}
avctx
->
channel_layout
=
alac_channel_layouts
[
alac
->
channels
-
1
];
avctx
->
channel_layout
=
ff_
alac_channel_layouts
[
alac
->
channels
-
1
];
if
((
ret
=
allocate_buffers
(
alac
))
<
0
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Error allocating buffers
\n
"
);
...
...
libavcodec/alac_data.c
0 → 100644
View file @
5e1bbb8c
/*
* ALAC encoder and decoder common data
*
* This file is part of Libav.
*
* Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Libav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/channel_layout.h"
#include "alac_data.h"
const
uint8_t
ff_alac_channel_layout_offsets
[
ALAC_MAX_CHANNELS
][
ALAC_MAX_CHANNELS
]
=
{
{
0
},
{
0
,
1
},
{
2
,
0
,
1
},
{
2
,
0
,
1
,
3
},
{
2
,
0
,
1
,
3
,
4
},
{
2
,
0
,
1
,
4
,
5
,
3
},
{
2
,
0
,
1
,
4
,
5
,
6
,
3
},
{
2
,
6
,
7
,
0
,
1
,
4
,
5
,
3
}
};
const
uint64_t
ff_alac_channel_layouts
[
ALAC_MAX_CHANNELS
+
1
]
=
{
AV_CH_LAYOUT_MONO
,
AV_CH_LAYOUT_STEREO
,
AV_CH_LAYOUT_SURROUND
,
AV_CH_LAYOUT_4POINT0
,
AV_CH_LAYOUT_5POINT0_BACK
,
AV_CH_LAYOUT_5POINT1_BACK
,
AV_CH_LAYOUT_6POINT1_BACK
,
AV_CH_LAYOUT_7POINT1_WIDE_BACK
,
0
};
const
enum
AlacRawDataBlockType
ff_alac_channel_elements
[
ALAC_MAX_CHANNELS
][
5
]
=
{
{
TYPE_SCE
,
},
{
TYPE_CPE
,
},
{
TYPE_SCE
,
TYPE_CPE
,
},
{
TYPE_SCE
,
TYPE_CPE
,
TYPE_SCE
},
{
TYPE_SCE
,
TYPE_CPE
,
TYPE_CPE
,
},
{
TYPE_SCE
,
TYPE_CPE
,
TYPE_CPE
,
TYPE_SCE
,
},
{
TYPE_SCE
,
TYPE_CPE
,
TYPE_CPE
,
TYPE_SCE
,
TYPE_SCE
,
},
{
TYPE_SCE
,
TYPE_CPE
,
TYPE_CPE
,
TYPE_CPE
,
TYPE_SCE
,
},
};
libavcodec/alac_data.h
0 → 100644
View file @
5e1bbb8c
/*
* ALAC encoder and decoder common data
*
* This file is part of Libav.
*
* Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Libav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVCODEC_ALAC_DATA_H
#define AVCODEC_ALAC_DATA_H
#include <stdint.h>
enum
AlacRawDataBlockType
{
/* At the moment, only SCE, CPE, LFE, and END are recognized. */
TYPE_SCE
,
TYPE_CPE
,
TYPE_CCE
,
TYPE_LFE
,
TYPE_DSE
,
TYPE_PCE
,
TYPE_FIL
,
TYPE_END
};
#define ALAC_MAX_CHANNELS 8
extern
const
uint8_t
ff_alac_channel_layout_offsets
[
ALAC_MAX_CHANNELS
][
ALAC_MAX_CHANNELS
];
extern
const
uint64_t
ff_alac_channel_layouts
[
ALAC_MAX_CHANNELS
+
1
];
extern
const
enum
AlacRawDataBlockType
ff_alac_channel_elements
[
ALAC_MAX_CHANNELS
][
5
];
#endif
/* AVCODEC_ALAC_DATA_H */
libavcodec/alacenc.c
View file @
5e1bbb8c
...
...
@@ -25,9 +25,9 @@
#include "internal.h"
#include "lpc.h"
#include "mathops.h"
#include "alac_data.h"
#define DEFAULT_FRAME_SIZE 4096
#define MAX_CHANNELS 8
#define ALAC_EXTRADATA_SIZE 36
#define ALAC_FRAME_HEADER_SIZE 55
#define ALAC_FRAME_FOOTER_SIZE 3
...
...
@@ -66,27 +66,27 @@ typedef struct AlacEncodeContext {
int
max_coded_frame_size
;
int
write_sample_size
;
int
extra_bits
;
int32_t
sample_buf
[
MAX_CHANNELS
][
DEFAULT_FRAME_SIZE
];
int32_t
sample_buf
[
2
][
DEFAULT_FRAME_SIZE
];
int32_t
predictor_buf
[
DEFAULT_FRAME_SIZE
];
int
interlacing_shift
;
int
interlacing_leftweight
;
PutBitContext
pbctx
;
RiceContext
rc
;
AlacLPCContext
lpc
[
MAX_CHANNELS
];
AlacLPCContext
lpc
[
2
];
LPCContext
lpc_ctx
;
AVCodecContext
*
avctx
;
}
AlacEncodeContext
;
static
void
init_sample_buffers
(
AlacEncodeContext
*
s
,
uint8_t
*
const
*
samples
)
static
void
init_sample_buffers
(
AlacEncodeContext
*
s
,
int
channels
,
uint8_t
const
*
samples
[
2
]
)
{
int
ch
,
i
;
int
shift
=
av_get_bytes_per_sample
(
s
->
avctx
->
sample_fmt
)
*
8
-
s
->
avctx
->
bits_per_raw_sample
;
#define COPY_SAMPLES(type) do { \
for (ch = 0; ch <
s->avctx->channels; ch++) {
\
for (ch = 0; ch <
channels; ch++) {
\
int32_t *bptr = s->sample_buf[ch]; \
const type *sptr = (const type *)samples[ch]; \
for (i = 0; i < s->frame_size; i++) \
...
...
@@ -128,15 +128,18 @@ static void encode_scalar(AlacEncodeContext *s, int x,
}
}
static
void
write_frame_header
(
AlacEncodeContext
*
s
)
static
void
write_element_header
(
AlacEncodeContext
*
s
,
enum
AlacRawDataBlockType
element
,
int
instance
)
{
int
encode_fs
=
0
;
if
(
s
->
frame_size
<
DEFAULT_FRAME_SIZE
)
encode_fs
=
1
;
put_bits
(
&
s
->
pbctx
,
3
,
s
->
avctx
->
channels
-
1
);
// No. of channels -1
put_bits
(
&
s
->
pbctx
,
16
,
0
);
// Seems to be zero
put_bits
(
&
s
->
pbctx
,
3
,
element
);
// element type
put_bits
(
&
s
->
pbctx
,
4
,
instance
);
// element instance
put_bits
(
&
s
->
pbctx
,
12
,
0
);
// unused header bits
put_bits
(
&
s
->
pbctx
,
1
,
encode_fs
);
// Sample count is in the header
put_bits
(
&
s
->
pbctx
,
2
,
s
->
extra_bits
>>
3
);
// Extra bytes (for 24-bit)
put_bits
(
&
s
->
pbctx
,
1
,
s
->
verbatim
);
// Audio block is verbatim
...
...
@@ -355,42 +358,51 @@ static void alac_entropy_coder(AlacEncodeContext *s)
}
}
static
int
write_frame
(
AlacEncodeContext
*
s
,
AVPacket
*
avpkt
,
uint8_t
*
const
*
samples
)
static
void
write_element
(
AlacEncodeContext
*
s
,
enum
AlacRawDataBlockType
element
,
int
instance
,
const
uint8_t
*
samples0
,
const
uint8_t
*
samples1
)
{
int
i
,
j
;
uint8_t
const
*
samples
[
2
]
=
{
samples0
,
samples1
};
int
i
,
j
,
channels
;
int
prediction_type
=
0
;
PutBitContext
*
pb
=
&
s
->
pbctx
;
init_put_bits
(
pb
,
avpkt
->
data
,
avpkt
->
size
)
;
channels
=
element
==
TYPE_CPE
?
2
:
1
;
if
(
s
->
verbatim
)
{
write_
frame_header
(
s
);
write_
element_header
(
s
,
element
,
instance
);
/* samples are channel-interleaved in verbatim mode */
if
(
s
->
avctx
->
sample_fmt
==
AV_SAMPLE_FMT_S32P
)
{
int
shift
=
32
-
s
->
avctx
->
bits_per_raw_sample
;
int32_t
*
const
*
samples_s32
=
(
int32_t
*
const
*
)
samples
;
int32_t
const
*
samples_s32
[
2
]
=
{
(
const
int32_t
*
)
samples0
,
(
const
int32_t
*
)
samples1
};
for
(
i
=
0
;
i
<
s
->
frame_size
;
i
++
)
for
(
j
=
0
;
j
<
s
->
avctx
->
channels
;
j
++
)
for
(
j
=
0
;
j
<
channels
;
j
++
)
put_sbits
(
pb
,
s
->
avctx
->
bits_per_raw_sample
,
samples_s32
[
j
][
i
]
>>
shift
);
}
else
{
int16_t
*
const
*
samples_s16
=
(
int16_t
*
const
*
)
samples
;
int16_t
const
*
samples_s16
[
2
]
=
{
(
const
int16_t
*
)
samples0
,
(
const
int16_t
*
)
samples1
};
for
(
i
=
0
;
i
<
s
->
frame_size
;
i
++
)
for
(
j
=
0
;
j
<
s
->
avctx
->
channels
;
j
++
)
for
(
j
=
0
;
j
<
channels
;
j
++
)
put_sbits
(
pb
,
s
->
avctx
->
bits_per_raw_sample
,
samples_s16
[
j
][
i
]);
}
}
else
{
init_sample_buffers
(
s
,
samples
);
write_frame_header
(
s
);
s
->
write_sample_size
=
s
->
avctx
->
bits_per_raw_sample
-
s
->
extra_bits
+
channels
-
1
;
init_sample_buffers
(
s
,
channels
,
samples
);
write_element_header
(
s
,
element
,
instance
);
if
(
s
->
avctx
->
channels
==
2
)
if
(
channels
==
2
)
alac_stereo_decorrelation
(
s
);
else
s
->
interlacing_shift
=
s
->
interlacing_leftweight
=
0
;
put_bits
(
pb
,
8
,
s
->
interlacing_shift
);
put_bits
(
pb
,
8
,
s
->
interlacing_leftweight
);
for
(
i
=
0
;
i
<
s
->
avctx
->
channels
;
i
++
)
{
for
(
i
=
0
;
i
<
channels
;
i
++
)
{
calc_predictor_params
(
s
,
i
);
put_bits
(
pb
,
4
,
prediction_type
);
...
...
@@ -407,7 +419,7 @@ static int write_frame(AlacEncodeContext *s, AVPacket *avpkt,
if
(
s
->
extra_bits
)
{
uint32_t
mask
=
(
1
<<
s
->
extra_bits
)
-
1
;
for
(
i
=
0
;
i
<
s
->
frame_size
;
i
++
)
{
for
(
j
=
0
;
j
<
s
->
avctx
->
channels
;
j
++
)
{
for
(
j
=
0
;
j
<
channels
;
j
++
)
{
put_bits
(
pb
,
s
->
extra_bits
,
s
->
sample_buf
[
j
][
i
]
&
mask
);
s
->
sample_buf
[
j
][
i
]
>>=
s
->
extra_bits
;
}
...
...
@@ -415,8 +427,7 @@ static int write_frame(AlacEncodeContext *s, AVPacket *avpkt,
}
// apply lpc and entropy coding to audio samples
for
(
i
=
0
;
i
<
s
->
avctx
->
channels
;
i
++
)
{
for
(
i
=
0
;
i
<
channels
;
i
++
)
{
alac_linear_predictor
(
s
,
i
);
// TODO: determine when this will actually help. for now it's not used.
...
...
@@ -425,12 +436,39 @@ static int write_frame(AlacEncodeContext *s, AVPacket *avpkt,
for
(
j
=
s
->
frame_size
-
1
;
j
>
0
;
j
--
)
s
->
predictor_buf
[
j
]
-=
s
->
predictor_buf
[
j
-
1
];
}
alac_entropy_coder
(
s
);
}
}
put_bits
(
pb
,
3
,
7
);
}
static
int
write_frame
(
AlacEncodeContext
*
s
,
AVPacket
*
avpkt
,
uint8_t
*
const
*
samples
)
{
PutBitContext
*
pb
=
&
s
->
pbctx
;
const
enum
AlacRawDataBlockType
*
ch_elements
=
ff_alac_channel_elements
[
s
->
avctx
->
channels
-
1
];
const
uint8_t
*
ch_map
=
ff_alac_channel_layout_offsets
[
s
->
avctx
->
channels
-
1
];
int
ch
,
element
,
sce
,
cpe
;
init_put_bits
(
pb
,
avpkt
->
data
,
avpkt
->
size
);
ch
=
element
=
sce
=
cpe
=
0
;
while
(
ch
<
s
->
avctx
->
channels
)
{
if
(
ch_elements
[
element
]
==
TYPE_CPE
)
{
write_element
(
s
,
TYPE_CPE
,
cpe
,
samples
[
ch_map
[
ch
]],
samples
[
ch_map
[
ch
+
1
]]);
cpe
++
;
ch
+=
2
;
}
else
{
write_element
(
s
,
TYPE_SCE
,
sce
,
samples
[
ch_map
[
ch
]],
NULL
);
sce
++
;
ch
++
;
}
element
++
;
}
put_bits
(
pb
,
3
,
TYPE_END
);
flush_put_bits
(
pb
);
return
put_bits_count
(
pb
)
>>
3
;
}
...
...
@@ -458,14 +496,6 @@ static av_cold int alac_encode_init(AVCodecContext *avctx)
avctx
->
frame_size
=
s
->
frame_size
=
DEFAULT_FRAME_SIZE
;
/* TODO: Correctly implement multi-channel ALAC.
It is similar to multi-channel AAC, in that it has a series of
single-channel (SCE), channel-pair (CPE), and LFE elements. */
if
(
avctx
->
channels
>
2
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"only mono or stereo input is currently supported
\n
"
);
return
AVERROR_PATCHWELCOME
;
}
if
(
avctx
->
sample_fmt
==
AV_SAMPLE_FMT_S32P
)
{
if
(
avctx
->
bits_per_raw_sample
!=
24
)
av_log
(
avctx
,
AV_LOG_WARNING
,
"encoding as 24 bits-per-sample
\n
"
);
...
...
@@ -597,8 +627,6 @@ static int alac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
s
->
verbatim
=
1
;
s
->
extra_bits
=
0
;
}
s
->
write_sample_size
=
avctx
->
bits_per_raw_sample
-
s
->
extra_bits
+
avctx
->
channels
-
1
;
out_bytes
=
write_frame
(
s
,
avpkt
,
frame
->
extended_data
);
...
...
@@ -606,7 +634,6 @@ static int alac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
/* frame too large. use verbatim mode */
s
->
verbatim
=
1
;
s
->
extra_bits
=
0
;
s
->
write_sample_size
=
avctx
->
bits_per_raw_sample
+
avctx
->
channels
-
1
;
out_bytes
=
write_frame
(
s
,
avpkt
,
frame
->
extended_data
);
}
...
...
@@ -624,6 +651,7 @@ AVCodec ff_alac_encoder = {
.
encode2
=
alac_encode_frame
,
.
close
=
alac_encode_close
,
.
capabilities
=
CODEC_CAP_SMALL_LAST_FRAME
,
.
channel_layouts
=
ff_alac_channel_layouts
,
.
sample_fmts
=
(
const
enum
AVSampleFormat
[]){
AV_SAMPLE_FMT_S32P
,
AV_SAMPLE_FMT_S16P
,
AV_SAMPLE_FMT_NONE
},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment