Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 5 additions & 9 deletions docs/faac.1
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ Input/output options
.TP
.BR --help-mp4
MP4 specific options
Quality-related options
.TP
.BR --help-advanced
Advanced options, only for testing purposes
Expand Down Expand Up @@ -109,10 +108,11 @@ The actual frequency is adjusted to maximize upper spectral band usage.
.SH INPUT/OUTPUT OPTIONS
.TP
.BR -o\ <\fIfilename\fP>
Set output file to X (only for one input file)
only for one input file; you can use *.aac, *.mp4, *.m4a or
*.m4b as file extension, and the file format will be set
automatically to ADTS or MP4).
Set output file to X (only for one input file). Format is auto-detected from
extension (.aac/.adts -> ADTS, .m4a/.mp4/.m4b -> MP4; default: MP4).
.TP
.BR -a
Use ADTS stream output format. Generate ADTS transport stream output.
.TP
.BR -
Use stdin/stdout.
Expand Down Expand Up @@ -169,10 +169,6 @@ Ignore wav length from header (useful with files over 4 GB)
Overwrite existing output file
.SH MP4 SPECIFIC OPTIONS
.TP
.BR -w

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe keep this option as a noop dummy for people having this hard code in their scripts?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about adding a dummy flag, but I'm worried about silent failures for users not passing -w and suddenly being surprised by .m4a over an .aac extension. Fail-fast behavior with a breaking change feels safer here so users know they need to update their scripts. What do you think?

Wrap AAC data in MP4 container. (default for *.mp4, *.m4a and
*.m4b)
.TP
.BR --tag\ <\fItagname,tagvalue\fP>
Add named tag (iTunes '----')
.TP
Expand Down
5 changes: 2 additions & 3 deletions docs/faac.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,8 @@ <h3>
<b>Options:</b><br>
<menu>
<li>
<kbd>-a X</kbd>
Set average bitrate to approximately X kbps per channel
(i.e. using -a 64 averages at 128 kbps/stereo).
<kbd>-a</kbd>
Comment thread
nschimme marked this conversation as resolved.
Use ADTS stream output format.
<li>
<kbd>-c &lt;bandwidth&gt;</kbd>
Set the bandwidth in Hz (default value depends on sample rate)
Expand Down
10 changes: 7 additions & 3 deletions frontend/encode_engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <fcntl.h>
#else
#include <sys/time.h>
#include <unistd.h>
#endif

#include "encode_engine.h"
Expand All @@ -45,6 +46,8 @@ void init_encode_options(encode_options_t *opts)
return;

memset(opts, 0, sizeof(*opts));
opts->container_mp4 = true;
opts->stream_format = FAAC_STREAM_ADTS;
opts->mpeg_version = FAAC_MPEG4;
opts->object_type = FAAC_OBJ_AUTO;
opts->joint_mode = FAAC_JOINT_MIXED;
Expand Down Expand Up @@ -570,8 +573,12 @@ int run_encoding_session_ext(const encode_options_t *opts,
else
{
#ifdef _WIN32
if (!opts->overwrite && win32_access_utf8(opts->output_filename, 0) == 0)
FAIL("Output file %s already exists\n", opts->output_filename);
outfile = win32_fopen_utf8(opts->output_filename, "wb");
#else
if (!opts->overwrite && access(opts->output_filename, 0) == 0)
FAIL("Output file %s already exists\n", opts->output_filename);
outfile = fopen(opts->output_filename, "wb");
#endif
if (!outfile)
Expand Down Expand Up @@ -616,7 +623,6 @@ int run_encoding_session_ext(const encode_options_t *opts,
uint32_t current_frame = 0;
uint64_t total_bytes_written = 0;
uint64_t current_input_samples = 0;
uint64_t encoded_samples = 0;
uint16_t max_frame_bytes = 0;
int samples_read = 0;

Expand Down Expand Up @@ -694,8 +700,6 @@ int run_encoding_session_ext(const encode_options_t *opts,
if (!write_output_bytes(outfile, bitbuf, (size_t)bytes_written))
FAIL("Output write failed\n");
}

encoded_samples += frame_size;
}

if (progress_cb)
Expand Down
27 changes: 16 additions & 11 deletions frontend/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,9 @@ static help_t help_qual[] = {

static help_t help_io[] = {
{"-o <filename>\tSet output file to X (only for one input file)\n",
"\t\tonly for one input file; you can use *.aac, *.mp4, *.m4a or\n"
"\t\t*.m4b as file extension, and the file format will be set\n"
"\t\tautomatically to ADTS or MP4).\n"},
"\t\tFormat is auto-detected from extension (.aac/.adts -> ADTS, .m4a/.mp4/.m4b -> MP4; default: MP4).\n"},
{"-a\t\tUse ADTS stream output format.\n",
"\t\tGenerate ADTS transport stream output.\n"},
{"-\t\tUse stdin/stdout\n",
"\t\tIf you simply use a hyphen/minus sign instead\n"
"\t\tof a filename, FAAC can encode directly from stdin,\n"
Expand Down Expand Up @@ -162,7 +162,6 @@ static help_t help_io[] = {
};

static help_t help_mp4[] = {
{"-w\tWrap AAC data in MP4 container (default for *.mp4, *.m4a and *.m4b)\n", NULL},
{"--tag <tagname,tagvalue> Add named tag (iTunes '----')\n", NULL},
{"--artist <name>\tSet artist name\n", NULL},
{"--artistsort <name>\tSet artist sort order\n", NULL},
Expand Down Expand Up @@ -453,6 +452,7 @@ int main(int argc, char *argv[])

char *aacFileName = NULL;
bool aacFileNameGiven = false;
bool stream_flag_given = false;
bool has_custom_tags = false;
const char *dieMessage = NULL;
int ret = 0;
Expand Down Expand Up @@ -543,7 +543,7 @@ int main(int argc, char *argv[])
{"mpeg-version", 1, 0, MPEGVERS_FLAG},
{"object-type", 1, 0, OBJTYPE_FLAG},
{"license", 0, 0, 'L'},
{"createmp4", 0, 0, 'w'},
{"adts", 0, 0, 'a'},
{"artist", 1, 0, ARTIST_FLAG},
{"artistsort", 1, 0, ARTIST_SORT_FLAG},
{"title", 1, 0, TITLE_FLAG},
Expand Down Expand Up @@ -572,7 +572,7 @@ int main(int argc, char *argv[])
};

int option_index = 0;
int c = getopt_long(argc, argv, "Hhb:m:o:rnc:q:PR:B:C:I:Xwv:L",
int c = getopt_long(argc, argv, "Hhb:m:o:rnc:q:PR:B:C:I:Xv:La",
long_options, &option_index);

if (c == -1)
Expand All @@ -594,12 +594,19 @@ int main(int argc, char *argv[])
case 'X':
opts.raw_endian = false;
break;
case 'a':
opts.container_mp4 = false;
opts.stream_format = FAAC_STREAM_ADTS;
stream_flag_given = true;
break;
case 'o':
aacFileName = strdup(optarg);
aacFileNameGiven = true;
break;
case 'r':
opts.container_mp4 = false;
opts.stream_format = FAAC_STREAM_RAW;
stream_flag_given = true;
break;
case 'c':
opts.bandwidth = atoi(optarg);
Expand Down Expand Up @@ -636,9 +643,6 @@ int main(int argc, char *argv[])
opts.raw_channels = (uint16_t)atoi(optarg);
opts.raw_pcm_input = true;
break;
case 'w':
opts.container_mp4 = true;
break;
case ARTIST_FLAG:
opts.metadata.artist = optarg;
break;
Expand Down Expand Up @@ -841,9 +845,10 @@ int main(int argc, char *argv[])
{
aacFileName = get_output_filename(opts.input_filename, opts.container_mp4);
}
else if (is_mp4_filename(aacFileName))
else if (!stream_flag_given)
{
opts.container_mp4 = true;
opts.container_mp4 = detect_container_mp4(aacFileName);
opts.stream_format = opts.container_mp4 ? FAAC_STREAM_RAW : FAAC_STREAM_ADTS;
}

if (opts.container_mp4)
Expand Down
29 changes: 27 additions & 2 deletions frontend/maingui.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ static DWORD WINAPI EncodeFile(LPVOID pParam)

opts.input_filename = utf8_input;
opts.output_filename = utf8_output;
opts.container_mp4 = utf8_output && is_mp4_filename(utf8_output);
opts.container_mp4 = utf8_output && detect_container_mp4(utf8_output);
opts.overwrite = true;

opts.object_type = (enum faac_object_type)GetComboData(hWnd, IDC_OBJECTTYPE, FAAC_OBJ_AUTO);
Expand Down Expand Up @@ -621,12 +621,37 @@ static INT_PTR CALLBACK DialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
case IDOK:
if (!Encoding)
{
WCHAR targetOutput[_MAX_PATH];
GetDlgItemTextW(hWnd, IDC_OUTPUTFILENAME, targetOutput, _MAX_PATH);

if (targetOutput[0] != L'\0')
{
char *utf8_out = win32_utf16_to_utf8(targetOutput);
if (utf8_out)
{
if (win32_access_utf8(utf8_out, 0) == 0)
{
int msgResult = MessageBoxW(hWnd,
L"The target output file already exists. Do you want to overwrite it?",
L"Confirm Overwrite",
MB_YESNO | MB_ICONQUESTION);
if (msgResult != IDYES)
{
free(utf8_out);
return TRUE;
}
_wremove(targetOutput);
}
free(utf8_out);
}
}

encode_thread_param_t *param = (encode_thread_param_t *)malloc(sizeof(encode_thread_param_t));
if (param)
{
param->hWnd = hWnd;
GetDlgItemTextW(hWnd, IDC_INPUTFILENAME, param->inputFilename, _MAX_PATH);
GetDlgItemTextW(hWnd, IDC_OUTPUTFILENAME, param->outputFilename, _MAX_PATH);
wcsncpy(param->outputFilename, targetOutput, _MAX_PATH);

SendDlgItemMessage(hWnd, IDC_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, GUI_PROGRESS_RANGE));
SendDlgItemMessage(hWnd, IDC_PROGRESS, PBM_SETPOS, 0, 0);
Expand Down
28 changes: 28 additions & 0 deletions frontend/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,20 @@ char *get_output_filename(const char *input_filename, bool container_mp4)
return aac_file_name;
}

bool is_adts_filename(const char *filename)
{
if (!filename)
return false;

const char *ext = find_extension(filename);
if (ext)
{
if (!strcasecmp(ext, ".aac") || !strcasecmp(ext, ".adts"))
return true;
}
return false;
}

bool is_mp4_filename(const char *filename)
{
if (!filename)
Expand All @@ -74,6 +88,20 @@ bool is_mp4_filename(const char *filename)
return false;
}

bool detect_container_mp4(const char *filename)
{
if (!filename)
return true;

if (!strcmp(filename, "-") || is_adts_filename(filename))
return false;

if (is_mp4_filename(filename))
return true;

return true;
}

bool check_image_header(const char *buf)
{
if (!buf)
Expand Down
8 changes: 7 additions & 1 deletion frontend/output.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,15 @@ extern "C" {
/* Generate default output filename based on input filename and container type */
char *get_output_filename(const char *input_filename, bool container_mp4);

/* Check if filename extension suggests MP4 container format */
/* Check if filename extension suggests ADTS stream format (.aac, .adts) */
bool is_adts_filename(const char *filename);

/* Check if filename extension suggests MP4 container format (.m4a, .mp4, .m4b) */
bool is_mp4_filename(const char *filename);

/* Auto-detect whether output file should use MP4 container format based on filename */
bool detect_container_mp4(const char *filename);

/* Check image header magic bytes (PNG, JPEG, GIF), used to validate
--cover-art data before it's embedded as an MP4 covr atom. */
bool check_image_header(const char *buf);
Expand Down
Loading