WAV reader: read >4 GiB files

Has data chunk size set to UINT32_MAX and size is deduced from file
length. This is consistent to what FFmpeg (MediaInfo, MPV and perhaps
others) does.
This commit is contained in:
Martin Pulec
2021-09-14 14:20:39 +02:00
parent f49012c9a1
commit c1fea40df7
3 changed files with 24 additions and 12 deletions

View File

@@ -42,6 +42,7 @@
#endif // HAVE_CONFIG_H
#include <inttypes.h>
#include <stdint.h>
#include "audio/utils.h"
#include "audio/wav_reader.h"
@@ -170,21 +171,29 @@ int read_wav_header(FILE *wav_file, struct wav_metadata *metadata)
if (strncmp(buffer, "data", 4) == 0) {
found_data_chunk = true;
uint32_t data_len = chunk_size;
long data_start = ftell(wav_file);
int64_t data_start = _ftelli64(wav_file);
CHECK(data_start, WAV_HDR_PARSE_READ_ERROR);
metadata->data_offset = data_start;
CHECK(fseek(wav_file, data_len, SEEK_CUR), WAV_HDR_PARSE_READ_ERROR);
long data_end = ftell(wav_file);
if (data_len == UINT32_MAX) {
// for UINT32_MAX deduce the length from file length (as FFmpeg does)
CHECK(_fseeki64(wav_file, 0, SEEK_END), WAV_HDR_PARSE_READ_ERROR);
} else {
CHECK(_fseeki64(wav_file, data_len, SEEK_CUR), WAV_HDR_PARSE_READ_ERROR);
}
int64_t data_end = _ftelli64(wav_file);
CHECK(data_end, WAV_HDR_PARSE_READ_ERROR);
long actual_data_size = data_end - data_start;
if (actual_data_size != (long) data_len) {
log_msg(LOG_LEVEL_ERROR, "[WAV] Premature end of file, read %ld of audio data, expected %ld.\n",
actual_data_size, (long) data_len);
return WAV_HDR_PARSE_READ_ERROR;
long long actual_data_size = data_end - data_start;
if (data_len == UINT32_MAX) {
metadata->data_size = actual_data_size;
} else {
if (actual_data_size != (long) data_len) {
log_msg(LOG_LEVEL_WARNING, "[WAV] Premature end of file, read %lld of audio data, expected %ld.\n",
actual_data_size, (long) data_len);
}
metadata->data_size = data_len;
}
metadata->data_size = data_len;
} else if (strncmp(buffer, "fmt ", 4) == 0) {
found_fmt_chunk = true;
if (chunk_size != 16 && chunk_size != 18 && chunk_size != 40) {
@@ -213,7 +222,7 @@ int read_wav_header(FILE *wav_file, struct wav_metadata *metadata)
return WAV_HDR_PARSE_READ_ERROR;
}
log_msg(LOG_LEVEL_VERBOSE, "[WAV] File parsed correctly - length %u bytes, offset %u.\n",
log_msg(LOG_LEVEL_VERBOSE, "[WAV] File parsed correctly - length %lld bytes, offset %lld.\n",
metadata->data_size, metadata->data_offset);
if (fseek(wav_file, metadata->data_offset, SEEK_SET) != 0) {
return WAV_HDR_PARSE_READ_ERROR;

View File

@@ -50,8 +50,8 @@ struct wav_metadata {
uint16_t valid_bits;
uint32_t channel_mask;
unsigned int data_size;
unsigned int data_offset; // from the beginning of file
long long data_size;
long long data_offset; // from the beginning of file
};
#define WAV_HDR_PARSE_OK 0

View File

@@ -215,5 +215,8 @@ static inline void *aligned_malloc(size_t size, size_t alignment)
#define ATTRIBUTE(a) __attribute__((a))
#define _ftelli64 ftell
#define _fseeki64 fseek
#endif /* _CONFIG_UNIX_H */
#endif /* NDEF WIN32 */