mirror of
https://github.com/nu774/fdkaac.git
synced 2025-03-12 15:00:10 +01:00
add --gapless-mode
This commit is contained in:
parent
ffc230a83e
commit
d317e29d46
95
src/m4af.c
95
src/m4af.c
@ -79,6 +79,7 @@ struct m4af_ctx_t {
|
||||
int64_t modification_time;
|
||||
int64_t mdat_pos;
|
||||
int64_t mdat_size;
|
||||
int priming_mode;
|
||||
int last_error;
|
||||
|
||||
m4af_itmf_entry_t *itmf_table;
|
||||
@ -148,6 +149,13 @@ int m4af_write(m4af_ctx_t *ctx, const void *data, uint32_t size)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static
|
||||
int m4af_write16(m4af_ctx_t *ctx, uint32_t data)
|
||||
{
|
||||
data = m4af_htob16(data);
|
||||
return m4af_write(ctx, &data, 2);
|
||||
}
|
||||
|
||||
static
|
||||
int m4af_write32(m4af_ctx_t *ctx, uint32_t data)
|
||||
{
|
||||
@ -277,6 +285,11 @@ void m4af_set_priming(m4af_ctx_t *ctx, uint32_t track_idx,
|
||||
track->padding = padding;
|
||||
}
|
||||
|
||||
void m4af_set_priming_mode(m4af_ctx_t *ctx, int mode)
|
||||
{
|
||||
ctx->priming_mode = mode;
|
||||
}
|
||||
|
||||
static
|
||||
int m4af_add_sample_entry(m4af_ctx_t *ctx, uint32_t track_idx,
|
||||
uint32_t size, uint32_t delta)
|
||||
@ -823,12 +836,50 @@ void m4af_write_stsd_box(m4af_ctx_t *ctx, uint32_t track_idx)
|
||||
m4af_update_box_size(ctx, pos);
|
||||
}
|
||||
|
||||
static
|
||||
void m4af_write_sbgp_box(m4af_ctx_t *ctx, uint32_t track_idx)
|
||||
{
|
||||
m4af_track_t *track = &ctx->track[track_idx];
|
||||
m4af_write(ctx,
|
||||
"\0\0\0\034" /* size: 28 */
|
||||
"sbgp" /* type */
|
||||
"\0" /* version */
|
||||
"\0\0\0" /* flags */
|
||||
"roll" /* grouping_type */
|
||||
"\0\0\0\001" /* entry_count: 1 */
|
||||
, 20);
|
||||
m4af_write32(ctx, track->num_samples);
|
||||
m4af_write32(ctx, 1); /* group_description_index */
|
||||
}
|
||||
|
||||
static
|
||||
void m4af_write_sgpd_box(m4af_ctx_t *ctx, uint32_t track_idx)
|
||||
{
|
||||
m4af_track_t *track = &ctx->track[track_idx];
|
||||
m4af_write(ctx,
|
||||
"\0\0\0\032" /* size */
|
||||
"sgpd" /* type */
|
||||
"\001" /* version */
|
||||
"\0\0\0" /* flags */
|
||||
"roll" /* grouping_type */
|
||||
"\0\0\0\002" /* default_length: 2 */
|
||||
"\0\0\0\001" /* entry_count: 1 */
|
||||
"\377\377" /* payload_data: -1 */
|
||||
, 26);
|
||||
}
|
||||
|
||||
static
|
||||
void m4af_write_stbl_box(m4af_ctx_t *ctx, uint32_t track_idx)
|
||||
{
|
||||
m4af_track_t *track = &ctx->track[track_idx];
|
||||
int64_t pos = m4af_tell(ctx);
|
||||
m4af_write(ctx, "\0\0\0\0stbl", 8);
|
||||
m4af_write_stsd_box(ctx, track_idx);
|
||||
if ((ctx->priming_mode & M4AF_PRIMING_MODE_EDTS) &&
|
||||
(track->encoder_delay || track->padding)) {
|
||||
m4af_write_sbgp_box(ctx, track_idx);
|
||||
m4af_write_sgpd_box(ctx, track_idx);
|
||||
}
|
||||
m4af_write_stts_box(ctx, track_idx);
|
||||
m4af_write_stsc_box(ctx, track_idx);
|
||||
m4af_write_stsz_box(ctx, track_idx);
|
||||
@ -962,6 +1013,42 @@ void m4af_write_mdia_box(m4af_ctx_t *ctx, uint32_t track_idx)
|
||||
m4af_update_box_size(ctx, pos);
|
||||
}
|
||||
|
||||
static
|
||||
void m4af_write_elst_box(m4af_ctx_t *ctx, uint32_t track_idx)
|
||||
{
|
||||
m4af_track_t *track = &ctx->track[track_idx];
|
||||
uint8_t version;
|
||||
int64_t duration = track->duration - track->encoder_delay - track->padding;
|
||||
int64_t pos = m4af_tell(ctx);
|
||||
duration = (double)duration / track->timescale * ctx->timescale + .5;
|
||||
version = (duration > UINT32_MAX);
|
||||
|
||||
m4af_write(ctx, "\0\0\0\0elst", 8);
|
||||
m4af_write(ctx, &version, 1);
|
||||
m4af_write(ctx, "\0\0\0", 3); /* flags */
|
||||
m4af_write32(ctx, 1); /* entry_count: 1 */
|
||||
if (version) {
|
||||
m4af_write64(ctx, duration);
|
||||
m4af_write64(ctx, track->encoder_delay);
|
||||
} else {
|
||||
m4af_write32(ctx, duration);
|
||||
m4af_write32(ctx, track->encoder_delay);
|
||||
}
|
||||
m4af_write16(ctx, 1); /* media_rate_integer */
|
||||
m4af_write16(ctx, 0); /* media_rate_fraction */
|
||||
m4af_update_box_size(ctx, pos);
|
||||
}
|
||||
|
||||
static
|
||||
void m4af_write_edts_box(m4af_ctx_t *ctx, uint32_t track_idx)
|
||||
{
|
||||
m4af_track_t *track = &ctx->track[track_idx];
|
||||
int64_t pos = m4af_tell(ctx);
|
||||
m4af_write(ctx, "\0\0\0\0edts", 8);
|
||||
m4af_write_elst_box(ctx, track_idx);
|
||||
m4af_update_box_size(ctx, pos);
|
||||
}
|
||||
|
||||
static
|
||||
void m4af_write_tkhd_box(m4af_ctx_t *ctx, uint32_t track_idx)
|
||||
{
|
||||
@ -1015,9 +1102,13 @@ void m4af_write_tkhd_box(m4af_ctx_t *ctx, uint32_t track_idx)
|
||||
static
|
||||
void m4af_write_trak_box(m4af_ctx_t *ctx, uint32_t track_idx)
|
||||
{
|
||||
m4af_track_t *track = &ctx->track[track_idx];
|
||||
int64_t pos = m4af_tell(ctx);
|
||||
m4af_write(ctx, "\0\0\0\0trak", 8);
|
||||
m4af_write_tkhd_box(ctx, track_idx);
|
||||
if ((ctx->priming_mode & M4AF_PRIMING_MODE_EDTS) &&
|
||||
(track->encoder_delay || track->padding))
|
||||
m4af_write_edts_box(ctx, track_idx);
|
||||
m4af_write_mdia_box(ctx, track_idx);
|
||||
m4af_update_box_size(ctx, pos);
|
||||
}
|
||||
@ -1227,7 +1318,9 @@ int m4af_finalize(m4af_ctx_t *ctx)
|
||||
}
|
||||
m4af_flush_chunk(ctx, i);
|
||||
}
|
||||
if (ctx->track[0].encoder_delay || ctx->track[0].padding)
|
||||
track = ctx->track;
|
||||
if ((ctx->priming_mode & M4AF_PRIMING_MODE_ITUNSMPB) &&
|
||||
(track->encoder_delay || track->padding))
|
||||
m4af_set_iTunSMPB(ctx);
|
||||
m4af_finalize_mdat(ctx);
|
||||
m4af_write_moov_box(ctx);
|
||||
|
@ -52,6 +52,12 @@ enum m4af_codec_type {
|
||||
M4AF_CODEC_TEXT = M4AF_FOURCC('t','e','x','t'),
|
||||
};
|
||||
|
||||
enum m4af_priming_mode {
|
||||
M4AF_PRIMING_MODE_ITUNSMPB = 1,
|
||||
M4AF_PRIMING_MODE_EDTS = 2,
|
||||
M4AF_PRIMING_MODE_BOTH = 3
|
||||
};
|
||||
|
||||
typedef int (*m4af_read_callback)(void *cookie, void *buffer, uint32_t size);
|
||||
typedef int (*m4af_write_callback)(void *cookie, const void *data,
|
||||
uint32_t size);
|
||||
@ -94,6 +100,8 @@ int m4af_set_decoder_specific_info(m4af_ctx_t *ctx, uint32_t track_idx,
|
||||
void m4af_set_priming(m4af_ctx_t *ctx, uint32_t track_idx,
|
||||
uint32_t encoder_delay, uint32_t padding);
|
||||
|
||||
void m4af_set_priming_mode(m4af_ctx_t *ctx, int mode);
|
||||
|
||||
void m4af_set_fixed_frame_duration(m4af_ctx_t *ctx, uint32_t track_idx,
|
||||
uint32_t length);
|
||||
|
||||
|
16
src/main.c
16
src/main.c
@ -148,6 +148,10 @@ PROGNAME " %s\n"
|
||||
" transport layer\n"
|
||||
"\n"
|
||||
" -o <filename> Output filename\n"
|
||||
" -G, --gapless-mode <n> Encoder delay signaling for gapless playback\n"
|
||||
" 0: iTunSMPB (default)\n"
|
||||
" 1: ISO standard (edts + sgpd)\n"
|
||||
" 2: Both\n"
|
||||
" --ignorelength Ignore length of WAV header\n"
|
||||
" -S, --silent Don't print progress messages\n"
|
||||
"\n"
|
||||
@ -199,6 +203,7 @@ typedef struct aacenc_param_ex_t {
|
||||
|
||||
char *input_filename;
|
||||
char *output_filename;
|
||||
unsigned gapless_mode;
|
||||
unsigned ignore_length;
|
||||
int silent;
|
||||
|
||||
@ -239,6 +244,7 @@ int parse_options(int argc, char **argv, aacenc_param_ex_t *params)
|
||||
{ "adts-crc-check", no_argument, 0, 'C' },
|
||||
{ "header-period", required_argument, 0, 'P' },
|
||||
|
||||
{ "gapless-mode", required_argument, 0, 'G' },
|
||||
{ "ignorelength", no_argument, 0, 'I' },
|
||||
{ "silent", no_argument, 0, 'S' },
|
||||
|
||||
@ -268,7 +274,7 @@ int parse_options(int argc, char **argv, aacenc_param_ex_t *params)
|
||||
params->afterburner = 1;
|
||||
|
||||
aacenc_getmainargs(&argc, &argv);
|
||||
while ((ch = getopt_long(argc, argv, "hp:b:m:w:a:Ls:f:CP:Io:SR",
|
||||
while ((ch = getopt_long(argc, argv, "hp:b:m:w:a:Ls:f:CP:G:Io:SR",
|
||||
long_options, 0)) != EOF) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
@ -338,6 +344,13 @@ int parse_options(int argc, char **argv, aacenc_param_ex_t *params)
|
||||
case 'o':
|
||||
params->output_filename = optarg;
|
||||
break;
|
||||
case 'G':
|
||||
if (sscanf(optarg, "%u", &n) != 1 || n > 2) {
|
||||
fprintf(stderr, "invalid arg for gapless-mode\n");
|
||||
return -1;
|
||||
}
|
||||
params->gapless_mode = n;
|
||||
break;
|
||||
case 'I':
|
||||
params->ignore_length = 1;
|
||||
break;
|
||||
@ -718,6 +731,7 @@ int main(int argc, char **argv)
|
||||
aacinfo.confSize);
|
||||
m4af_set_fixed_frame_duration(m4af, 0,
|
||||
framelen >> downsampled_timescale);
|
||||
m4af_set_priming_mode(m4af, params.gapless_mode + 1);
|
||||
m4af_begin_write(m4af);
|
||||
}
|
||||
frame_count = encode(wavf, encoder, aacinfo.frameLength, ofp, m4af,
|
||||
|
Loading…
x
Reference in New Issue
Block a user