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

Reply via email to