Current section

5 Versions

Jump to

Compare versions

6 files changed
+107 additions
-103 deletions
  @@ -41,6 +41,6 @@ brew install fdk-aac
41 41
42 42 Copyright 2018, [Software Mansion](https://swmansion.com/?utm_source=git&utm_medium=readme&utm_campaign=membrane)
43 43
44 - [![Software Mansion](https://membraneframework.github.io/static/logo/swm_logo_readme.png)](https://swmansion.com/?utm_source=git&utm_medium=readme&utm_campaign=membrane)
44 + [![Software Mansion](https://logo.swmansion.com/logo?color=white&variant=desktop&width=200&tag=membrane-github)](https://swmansion.com/?utm_source=git&utm_medium=readme&utm_campaign=membrane)
45 45
46 46 Licensed under the [Apache License, Version 2.0](LICENSE)
  @@ -2,7 +2,8 @@
2 2
3 3 /**
4 4 * AAC Decoder implementation.
5 - * Heavily inspired by https://github.com/FFmpeg/FFmpeg/blob/master/libavcodec/libfdk-aacdec.c
5 + * Heavily inspired by
6 + * https://github.com/FFmpeg/FFmpeg/blob/master/libavcodec/libfdk-aacdec.c
6 7 */
7 8
8 9 #define DECODER_MAX_CHANNELS 8
  @@ -10,11 +11,12 @@
10 11
11 12 /**
12 13 * Initializes AAC Decoder and returns State resource.
13 - *
14 + *
14 15 * On success, returns {:ok, decoder_state}
15 16 * In case of error, returns:
16 17 * - {:error, :unknown} - If AAC decoder cannot be initialized
17 - * - {:error, :no_memory} - If there's not enough memory to initialize AAC buffer
18 + * - {:error, :no_memory} - If there's not enough memory to initialize AAC
19 + * buffer
18 20 */
19 21 UNIFEX_TERM create(UnifexEnv *env) {
20 22 State *state = unifex_alloc_state(env);
  @@ -40,9 +42,9 @@ UNIFEX_TERM create(UnifexEnv *env) {
40 42
41 43 /**
42 44 * Returns AAC stream metadata
43 - *
45 + *
44 46 * Expects Native resource as argument
45 - *
47 + *
46 48 * Returns:
47 49 * - {:ok, {frame_size, sample_rate, channels}}
48 50 */
  @@ -51,22 +53,19 @@ UNIFEX_TERM get_metadata(UnifexEnv *env, State *state) {
51 53
52 54 CStreamInfo *stream_info = aacDecoder_GetStreamInfo(state->handle);
53 55
54 - res = get_metadata_result(
55 - env,
56 - stream_info->frameSize,
57 - stream_info->sampleRate,
58 - stream_info->numChannels);
56 + res = get_metadata_result(env, stream_info->frameSize,
57 + stream_info->sampleRate, stream_info->numChannels);
59 58 return res;
60 59 }
61 60
62 61 /**
63 62 * Fills internal AAC Decoder buffer with input buffer
64 - *
63 + *
65 64 * Expects:
66 65 * - Buffer to decode
67 66 * - Native resource
68 67 * as arguments
69 - *
68 + *
70 69 * Returns one of:
71 70 * - {:ok}
72 71 * - {:error, :invalid_data}
  @@ -76,18 +75,17 @@ UNIFEX_TERM fill(UnifexEnv *env, UnifexPayload *in_payload, State *state) {
76 75 AAC_DECODER_ERROR err;
77 76 UINT valid = in_payload->size;
78 77
79 - err = aacDecoder_Fill(
80 - state->handle,
81 - &in_payload->data,
82 - &in_payload->size,
83 - &valid);
78 + err = aacDecoder_Fill(state->handle, &in_payload->data, &in_payload->size,
79 + &valid);
84 80 if (err != AAC_DEC_OK) {
85 81 MEMBRANE_WARN(env, "AAC: aacDecoder_Fill() failed: %x\n", err);
86 82 return fill_result_error_invalid_data(env);
87 83 }
88 84 if (valid != 0) {
89 - //See: https://github.com/mstorsjo/fdk-aac/blob/95858d7bd36f19bde4a9595e2bd68f195215b164/libAACdec/include/aacdecoder_lib.h#L1014
90 - MEMBRANE_WARN(env, "AAC: aacDecoder_Fill() left %d bytes in input buffer\n", valid);
85 + // See:
86 + // https://github.com/mstorsjo/fdk-aac/blob/95858d7bd36f19bde4a9595e2bd68f195215b164/libAACdec/include/aacdecoder_lib.h#L1014
87 + MEMBRANE_WARN(env, "AAC: aacDecoder_Fill() left %d bytes in input buffer\n",
88 + valid);
91 89 }
92 90
93 91 res = fill_result_ok(env);
  @@ -96,12 +94,12 @@ UNIFEX_TERM fill(UnifexEnv *env, UnifexPayload *in_payload, State *state) {
96 94
97 95 /**
98 96 * Decodes one input frame.
99 - *
97 + *
100 98 * Expects:
101 99 * - Buffer to decode
102 100 * - Native resource
103 101 * as arguments
104 - *
102 + *
105 103 * Returns one of:
106 104 * - {:ok, {decoded_frame, frame_size, sample_rate, channels}}
107 105 * decoded audio frame with stream info
  @@ -109,17 +107,16 @@ UNIFEX_TERM fill(UnifexEnv *env, UnifexPayload *in_payload, State *state) {
109 107 * - {:error, :not_enough_bits}
110 108 * - {:error, :unknown}
111 109 */
112 - UNIFEX_TERM decode_frame(UnifexEnv *env, UnifexPayload *in_payload, State *state) {
110 + UNIFEX_TERM decode_frame(UnifexEnv *env, UnifexPayload *in_payload,
111 + State *state) {
113 112 UNIFEX_TERM res;
114 113 AAC_DECODER_ERROR err;
115 114
116 - err = aacDecoder_DecodeFrame(
117 - state->handle,
118 - (INT_PCM *)state->decoder_buffer,
119 - state->decoder_buffer_size / sizeof(INT_PCM),
120 - 0);
115 + err = aacDecoder_DecodeFrame(state->handle, (INT_PCM *)state->decoder_buffer,
116 + state->decoder_buffer_size / sizeof(INT_PCM), 0);
121 117 if (err == AAC_DEC_NOT_ENOUGH_BITS) {
122 - MEMBRANE_WARN(env, "AAC: aacDecoder_DecodeFrame() - not enough bits supplied");
118 + MEMBRANE_WARN(env,
119 + "AAC: aacDecoder_DecodeFrame() - not enough bits supplied");
123 120 return decode_frame_result_error_not_enough_bits(env);
124 121 }
125 122 if (err != AAC_DEC_OK) {
  @@ -129,16 +126,13 @@ UNIFEX_TERM decode_frame(UnifexEnv *env, UnifexPayload *in_payload, State *state
129 126
130 127 CStreamInfo *stream_info = aacDecoder_GetStreamInfo(state->handle);
131 128
132 - UINT out_payload_size = stream_info->frameSize * stream_info->numChannels * sizeof(INT_PCM);
133 - UnifexPayload *out_payload = unifex_payload_alloc(env, in_payload->type, out_payload_size);
134 - memcpy(
135 - out_payload->data,
136 - state->decoder_buffer,
137 - out_payload_size);
129 + UINT out_payload_size =
130 + stream_info->frameSize * stream_info->numChannels * sizeof(INT_PCM);
131 + UnifexPayload *out_payload =
132 + unifex_payload_alloc(env, in_payload->type, out_payload_size);
133 + memcpy(out_payload->data, state->decoder_buffer, out_payload_size);
138 134
139 - res = decode_frame_result_ok(
140 - env,
141 - out_payload);
135 + res = decode_frame_result_ok(env, out_payload);
142 136 unifex_payload_release_ptr(&out_payload);
143 137 return res;
144 138 }
  @@ -3,14 +3,13 @@
3 3 #include <fdk-aac/aacdecoder_lib.h>
4 4 #include <membrane/membrane.h>
5 5 #define MEMBRANE_LOG_TAG "Membrane.Element.FDK.AAC.DecoderNative"
6 - #include <membrane/log.h>
7 6 #include "stdint.h"
7 + #include <membrane/log.h>
8 8
9 9 typedef struct _DecoderState UnifexNifState;
10 10 typedef UnifexNifState State;
11 11
12 - struct _DecoderState
13 - {
12 + struct _DecoderState {
14 13 HANDLE_AACDECODER handle;
15 14 uint8_t *decoder_buffer;
16 15 int decoder_buffer_size;
  @@ -1,7 +1,7 @@
1 1 #include "encoder.h"
2 2
3 3 static const int SAMPLE_SIZE = 2;
4 - static const int MAX_AAC_BUFFER_SIZE = 8192; // TODO: Validate
4 + static const int MAX_AAC_BUFFER_SIZE = 8192; // TODO: Validate
5 5
6 6 static const int PROFILE_AAC_HE = 5;
7 7 static const int PROFILE_AAC_HE_v2 = 29;
  @@ -9,7 +9,8 @@ static const int PROFILE_MPEG2_AAC_HE = 132;
9 9
10 10 /**
11 11 * AAC Encoder implementation.
12 - * Heavily inspired by https://github.com/FFmpeg/FFmpeg/blob/master/libavcodec/libfdk-aacenc.c
12 + * Heavily inspired by
13 + * https://github.com/FFmpeg/FFmpeg/blob/master/libavcodec/libfdk-aacenc.c
13 14 */
14 15
15 16 /**
  @@ -17,55 +18,59 @@ static const int PROFILE_MPEG2_AAC_HE = 132;
17 18 */
18 19 char *get_error_message(AACENC_ERROR err) {
19 20 switch (err) {
20 - case AACENC_OK:
21 - return "No error";
22 - case AACENC_INVALID_HANDLE:
23 - return "Invalid handle";
24 - case AACENC_MEMORY_ERROR:
25 - return "Memory allocation error";
26 - case AACENC_UNSUPPORTED_PARAMETER:
27 - return "Unsupported parameter";
28 - case AACENC_INVALID_CONFIG:
29 - return "Invalid config";
30 - case AACENC_INIT_ERROR:
31 - return "Initialization error";
32 - case AACENC_INIT_AAC_ERROR:
33 - return "AAC library initialization error";
34 - case AACENC_INIT_SBR_ERROR:
35 - return "SBR library initialization error";
36 - case AACENC_INIT_TP_ERROR:
37 - return "Transport library initialization error";
38 - case AACENC_INIT_META_ERROR:
39 - return "Metadata library initialization error";
40 - case AACENC_ENCODE_ERROR:
41 - return "Encoding error";
42 - case AACENC_ENCODE_EOF:
43 - return "End of file";
44 - default:
45 - return "Unknown error";
21 + case AACENC_OK:
22 + return "No error";
23 + case AACENC_INVALID_HANDLE:
24 + return "Invalid handle";
25 + case AACENC_MEMORY_ERROR:
26 + return "Memory allocation error";
27 + case AACENC_UNSUPPORTED_PARAMETER:
28 + return "Unsupported parameter";
29 + case AACENC_INVALID_CONFIG:
30 + return "Invalid config";
31 + case AACENC_INIT_ERROR:
32 + return "Initialization error";
33 + case AACENC_INIT_AAC_ERROR:
34 + return "AAC library initialization error";
35 + case AACENC_INIT_SBR_ERROR:
36 + return "SBR library initialization error";
37 + case AACENC_INIT_TP_ERROR:
38 + return "Transport library initialization error";
39 + case AACENC_INIT_META_ERROR:
40 + return "Metadata library initialization error";
41 + case AACENC_ENCODE_ERROR:
42 + return "Encoding error";
43 + case AACENC_ENCODE_EOF:
44 + return "End of file";
45 + default:
46 + return "Unknown error";
46 47 }
47 48 }
48 49
49 50 /**
50 51 * Initializes AAC Encoder and returns State resource.
51 - *
52 + *
52 53 * Expects:
53 - * - channels - Number of channels. For now, only supports either 1 or 2 channels.
54 + * - channels - Number of channels. For now, only supports either 1 or 2
55 + * channels.
54 56 * - sample_rate - Sample rate.
55 57 * - aot - Audio Object Type.
56 - * - bitrate_mode - 0 for CBR, 1-5 for VBR mode. See: http://wiki.hydrogenaud.io/index.php?title=Fraunhofer_FDK_AAC#Bitrate_Modes
57 - *
58 + * - bitrate_mode - 0 for CBR, 1-5 for VBR mode. See:
59 + * http://wiki.hydrogenaud.io/index.php?title=Fraunhofer_FDK_AAC#Bitrate_Modes
60 + *
58 61 * On success, returns {:ok, encoder_state}
59 62 * In case of error, returns:
60 63 * - {:error, reason}
61 64 */
62 - UNIFEX_TERM create(UnifexEnv *env, int channels, int sample_rate, int aot, int bitrate_mode, int bitrate) {
65 + UNIFEX_TERM create(UnifexEnv *env, int channels, int sample_rate, int aot,
66 + int bitrate_mode, int bitrate) {
63 67 State *state = unifex_alloc_state(env);
64 68 state->channels = channels;
65 69
66 70 AACENC_ERROR err;
67 71 CHANNEL_MODE channel_mode;
68 - // See: https://wiki.multimedia.cx/index.php/Understanding_AAC#Frames_And_Syntax_Elements
72 + // See:
73 + // https://wiki.multimedia.cx/index.php/Understanding_AAC#Frames_And_Syntax_Elements
69 74 int sce = 0, cpe = 0;
70 75
71 76 // Initialize AAC Encoder handle
  @@ -98,23 +103,24 @@ UNIFEX_TERM create(UnifexEnv *env, int channels, int sample_rate, int aot, int b
98 103
99 104 // Set channels configuration
100 105 switch (channels) {
101 - case 1:
102 - channel_mode = MODE_1;
103 - sce = 1;
104 - cpe = 0;
105 - break;
106 - case 2:
107 - channel_mode = MODE_2;
108 - sce = 0;
109 - cpe = 1;
110 - break;
111 - default:
112 - MEMBRANE_WARN(env, "AAC: Unsupported number of channels: %d", channels);
113 - return create_result_error(env, get_error_message(err));
106 + case 1:
107 + channel_mode = MODE_1;
108 + sce = 1;
109 + cpe = 0;
110 + break;
111 + case 2:
112 + channel_mode = MODE_2;
113 + sce = 0;
114 + cpe = 1;
115 + break;
116 + default:
117 + MEMBRANE_WARN(env, "AAC: Unsupported number of channels: %d", channels);
118 + return create_result_error(env, get_error_message(err));
114 119 }
115 120 err = aacEncoder_SetParam(state->handle, AACENC_CHANNELMODE, channel_mode);
116 121 if (err != AACENC_OK) {
117 - MEMBRANE_WARN(env, "AAC: Unable to set channel mode %d: %x\n", channel_mode, err);
122 + MEMBRANE_WARN(env, "AAC: Unable to set channel mode %d: %x\n", channel_mode,
123 + err);
118 124 return create_result_error(env, get_error_message(err));
119 125 }
120 126
  @@ -128,7 +134,9 @@ UNIFEX_TERM create(UnifexEnv *env, int channels, int sample_rate, int aot, int b
128 134 if (bitrate_mode) {
129 135 // VBR
130 136 if (bitrate_mode < 1 || bitrate_mode > 5) {
131 - MEMBRANE_WARN(env, "AAC: Unable to set VBR mode: %d. VBR quality should be 1-5\n", bitrate_mode);
137 + MEMBRANE_WARN(
138 + env, "AAC: Unable to set VBR mode: %d. VBR quality should be 1-5\n",
139 + bitrate_mode);
132 140 return create_result_error(env, "invalid_vbr");
133 141 }
134 142 err = aacEncoder_SetParam(state->handle, AACENC_BITRATEMODE, bitrate_mode);
  @@ -138,14 +146,14 @@ UNIFEX_TERM create(UnifexEnv *env, int channels, int sample_rate, int aot, int b
138 146 }
139 147 } else {
140 148 // CBR
141 - // If bitrate is not specified by the user, this will estimate the bitrate, following the "rule of thumb"
142 - // described here: https://trac.ffmpeg.org/wiki/Encode/AAC#fdk_cbr
143 - // This is based on: https://github.com/FFmpeg/FFmpeg/blob/master/libavcodec/libfdk-aacenc.c#L245
149 + // If bitrate is not specified by the user, this will estimate the bitrate,
150 + // following the "rule of thumb" described here:
151 + // https://trac.ffmpeg.org/wiki/Encode/AAC#fdk_cbr This is based on:
152 + // https://github.com/FFmpeg/FFmpeg/blob/master/libavcodec/libfdk-aacenc.c#L245
144 153 if (!bitrate) {
145 154 bitrate = (96 * sce + 128 * cpe) * sample_rate / 44;
146 155 }
147 - if (aot == PROFILE_AAC_HE ||
148 - aot == PROFILE_AAC_HE_v2 ||
156 + if (aot == PROFILE_AAC_HE || aot == PROFILE_AAC_HE_v2 ||
149 157 aot == PROFILE_MPEG2_AAC_HE) {
150 158 bitrate /= 2;
151 159 }
  @@ -176,18 +184,20 @@ UNIFEX_TERM create(UnifexEnv *env, int channels, int sample_rate, int aot, int b
176 184
177 185 /**
178 186 * Encodes one input frame.
179 - *
187 + *
180 188 * Expects:
181 189 * - Buffer to encoder
182 190 * - Native resource
183 191 * as arguments
184 - *
192 + *
185 193 * Returns on of:
186 194 * - {:ok, {encoded_frame}} - Encoded AAC frame
187 - * - {:error, :no_data} - When supplied input buffer does not contain enough data to encode a single frame
195 + * - {:error, :no_data} - When supplied input buffer does not contain enough
196 + * data to encode a single frame
188 197 * - {:error, reason} - When native encoding failed
189 198 */
190 - UNIFEX_TERM encode_frame(UnifexEnv *env, UnifexPayload *in_payload, State *state) {
199 + UNIFEX_TERM encode_frame(UnifexEnv *env, UnifexPayload *in_payload,
200 + State *state) {
191 201 UNIFEX_TERM res;
192 202 AACENC_ERROR err;
193 203
  @@ -242,8 +252,9 @@ UNIFEX_TERM encode_frame(UnifexEnv *env, UnifexPayload *in_payload, State *state
242 252 return encode_frame_result_error_no_data(env);
243 253 }
244 254
245 - UnifexPayload *out_payload = unifex_payload_alloc(env, UNIFEX_PAYLOAD_BINARY, out_buffer_size);
246 - memcpy(out_payload->data, state->aac_buffer, out_buffer_size);
255 + UnifexPayload *out_payload =
256 + unifex_payload_alloc(env, UNIFEX_PAYLOAD_BINARY, out_args.numOutBytes);
257 + memcpy(out_payload->data, state->aac_buffer, out_args.numOutBytes);
247 258 res = encode_frame_result_ok(env, out_payload);
248 259 unifex_payload_release_ptr(&out_payload);
249 260 return res;
  @@ -55,4 +55,4 @@
55 55 {<<"optional">>,false},
56 56 {<<"repository">>,<<"hexpm">>},
57 57 {<<"requirement">>,<<"~> 0.2.0">>}]]}.
58 - {<<"version">>,<<"0.2.0">>}.
58 + {<<"version">>,<<"0.2.1">>}.
Loading more files…