diff --git a/docs/faac.1 b/docs/faac.1 index fc86e3c4d..d942bcac7 100644 --- a/docs/faac.1 +++ b/docs/faac.1 @@ -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 @@ -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. @@ -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 -Wrap AAC data in MP4 container. (default for *.mp4, *.m4a and -*.m4b) -.TP .BR --tag\ <\fItagname,tagvalue\fP> Add named tag (iTunes '----') .TP diff --git a/docs/faac.html b/docs/faac.html index 9ad50589a..404c9960e 100644 --- a/docs/faac.html +++ b/docs/faac.html @@ -43,9 +43,8 @@

Options:
  • --a X - Set average bitrate to approximately X kbps per channel - (i.e. using -a 64 averages at 128 kbps/stereo). +-a + Use ADTS stream output format.
  • -c <bandwidth> Set the bandwidth in Hz (default value depends on sample rate) diff --git a/frontend/encode_engine.c b/frontend/encode_engine.c index 1b4b2a78c..0e8628050 100644 --- a/frontend/encode_engine.c +++ b/frontend/encode_engine.c @@ -32,6 +32,7 @@ #include #else #include +#include #endif #include "encode_engine.h" @@ -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; @@ -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) @@ -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; @@ -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) diff --git a/frontend/main.c b/frontend/main.c index 6288da436..07e5dffc8 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -123,9 +123,9 @@ static help_t help_qual[] = { static help_t help_io[] = { {"-o \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" @@ -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 Add named tag (iTunes '----')\n", NULL}, {"--artist \tSet artist name\n", NULL}, {"--artistsort \tSet artist sort order\n", NULL}, @@ -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; @@ -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}, @@ -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) @@ -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); @@ -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; @@ -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) diff --git a/frontend/maingui.c b/frontend/maingui.c index bb72ae8b6..a0907bdb2 100644 --- a/frontend/maingui.c +++ b/frontend/maingui.c @@ -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); @@ -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); diff --git a/frontend/output.c b/frontend/output.c index a9367edc2..086b50e60 100644 --- a/frontend/output.c +++ b/frontend/output.c @@ -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) @@ -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) diff --git a/frontend/output.h b/frontend/output.h index 34eb929aa..37dd817e3 100644 --- a/frontend/output.h +++ b/frontend/output.h @@ -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);