I made some changes to the previous patch. I don't know why I originally
didn't put the output buffering to piped output too but that is now
moved to cover both file and pipe output.
Additionally this patch informs the Windows filesystem in advance about
the decoded size to eliminate NTFS fragmentation.
On 25.9.2014 23:01, Janne Hyvärinen wrote:
Decoding flac files is also prone to producing fragmented files. NTFS
has the ability to completely avoid fragmentation if it is told the
file size before hand, but that would require using special
Windows-only functions. Increasing the write buffer from the default
512 bytes to 10 MB already reduces the problem tremendously.
_______________________________________________
flac-dev mailing list
[email protected]
http://lists.xiph.org/mailman/listinfo/flac-dev
diff --git a/src/flac/decode.c b/src/flac/decode.c
index 5e5e17a..90e0b1a 100644
--- a/src/flac/decode.c
+++ b/src/flac/decode.c
@@ -101,7 +101,7 @@ static FLAC__bool is_big_endian_host_;
static FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool
is_ogg, FLAC__bool use_first_serial_number, long serial_number, FileFormat
format, FLAC__bool treat_warnings_as_errors, FLAC__bool
continue_through_decode_errors, FLAC__bool channel_map_none,
replaygain_synthesis_spec_t replaygain_synthesis_spec, FLAC__bool
analysis_mode, analysis_options aopts, utils__SkipUntilSpecification
*skip_specification, utils__SkipUntilSpecification *until_specification,
utils__CueSpecification *cue_specification, foreign_metadata_t
*foreign_metadata, const char *infilename, const char *outfilename);
static void DecoderSession_destroy(DecoderSession *d, FLAC__bool
error_occurred);
static FLAC__bool DecoderSession_init_decoder(DecoderSession *d, const char
*infilename);
-static FLAC__bool DecoderSession_process(DecoderSession *d);
+static FLAC__bool DecoderSession_process(DecoderSession *d, const char
*outfilename);
static int DecoderSession_finish_ok(DecoderSession *d);
static int DecoderSession_finish_error(DecoderSession *d);
static FLAC__bool
canonicalize_until_specification(utils__SkipUntilSpecification *spec, const
char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64
total_samples_in_input);
@@ -177,7 +177,7 @@ int flac__decode_file(const char *infilename, const char
*outfilename, FLAC__boo
if(!DecoderSession_init_decoder(&decoder_session, infilename))
return DecoderSession_finish_error(&decoder_session);
- if(!DecoderSession_process(&decoder_session))
+ if(!DecoderSession_process(&decoder_session, outfilename))
return DecoderSession_finish_error(&decoder_session);
return DecoderSession_finish_ok(&decoder_session);
@@ -252,6 +252,7 @@ FLAC__bool DecoderSession_construct(DecoderSession *d,
FLAC__bool is_ogg, FLAC__
return false;
}
}
+ setvbuf(d->fout, NULL, _IOFBF, 10*1024*1024); /* 10MB output
buffer to help reduce disk fragmentation */
}
if(analysis_mode)
@@ -317,7 +318,7 @@ FLAC__bool DecoderSession_init_decoder(DecoderSession
*decoder_session, const ch
return true;
}
-FLAC__bool DecoderSession_process(DecoderSession *d)
+FLAC__bool DecoderSession_process(DecoderSession *d, const char *outfilename)
{
if(!FLAC__stream_decoder_process_until_end_of_metadata(d->decoder)) {
flac__utils_printf(stderr, 2, "\n");
@@ -366,6 +367,29 @@ FLAC__bool DecoderSession_process(DecoderSession *d)
/* write the WAVE/AIFF headers if necessary */
if(!d->analysis_mode && !d->test_only && d->format != FORMAT_RAW) {
+#ifdef _WIN32
+ if(strcmp(outfilename, "-") && d->total_samples > 0) {
+ HANDLE fh = CreateFile_utf8(outfilename,
GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if(fh != INVALID_HANDLE_VALUE) {
+ if (GetFileType(fh) == FILE_TYPE_DISK) {
+ LARGE_INTEGER size, pos;
+
+ size.QuadPart = d->total_samples *
d->channels * ((d->bps+7)/8) + 512;
+ if(d->foreign_metadata) {
+ size_t i;
+ for(i =
d->format==FORMAT_RF64?2:1; i < d->foreign_metadata->num_blocks; i++) {
+ if(i !=
d->foreign_metadata->format_block && i != d->foreign_metadata->audio_block)
+ size.QuadPart
+= d->foreign_metadata->blocks[i].size;
+ }
+ }
+
+ if(SetFilePointerEx(fh, size, NULL,
FILE_CURRENT)) /* tell filesystem the expected filesize to eliminate
fragmentation */
+ SetEndOfFile(fh);
+ }
+ CloseHandle(fh);
+ }
+ }
+#endif
if(!write_iff_headers(d->fout, d, d->total_samples)) {
d->abort_flag = true;
return false;
_______________________________________________
flac-dev mailing list
[email protected]
http://lists.xiph.org/mailman/listinfo/flac-dev