Skip to content
Snippets Groups Projects
Commit be71be7e authored by Sean Bright's avatar Sean Bright
Browse files

format_pcm: Track actual header size of .au files

Sun's Au file format has a minimum data offset 24 bytes, but this
offset is encoded in each .au file. Instead of assuming the minimum,
read the actual value and store it for later use.

ASTERISK-20984 #close
Reported by: Roman S.
Patches:
	asterisk-1.8.20.0-au-clicks-2.diff (license #6474) patch
	uploaded by Roman S.

Change-Id: I524022fb19ff2fd5af2cc2d669d27a780ab2057c
parent 2e6075c5
Branches
Tags
No related merge requests found
...@@ -231,7 +231,7 @@ static int pcm_write(struct ast_filestream *fs, struct ast_frame *f) ...@@ -231,7 +231,7 @@ static int pcm_write(struct ast_filestream *fs, struct ast_frame *f)
/* SUN .au support routines */ /* SUN .au support routines */
#define AU_HEADER_SIZE 24 #define MIN_AU_HEADER_SIZE 24
#define AU_HEADER(var) uint32_t var[6] #define AU_HEADER(var) uint32_t var[6]
#define AU_HDR_MAGIC_OFF 0 #define AU_HDR_MAGIC_OFF 0
...@@ -266,7 +266,11 @@ static int pcm_write(struct ast_filestream *fs, struct ast_frame *f) ...@@ -266,7 +266,11 @@ static int pcm_write(struct ast_filestream *fs, struct ast_frame *f)
#endif #endif
#endif #endif
static int check_header(FILE *f) struct au_desc {
uint32_t hdr_size;
};
static int check_header(struct ast_filestream *fs)
{ {
AU_HEADER(header); AU_HEADER(header);
uint32_t magic; uint32_t magic;
...@@ -276,7 +280,10 @@ static int check_header(FILE *f) ...@@ -276,7 +280,10 @@ static int check_header(FILE *f)
uint32_t sample_rate; uint32_t sample_rate;
uint32_t channels; uint32_t channels;
if (fread(header, 1, AU_HEADER_SIZE, f) != AU_HEADER_SIZE) { struct au_desc *desc = fs->_private;
FILE *f = fs->f;
if (fread(header, 1, MIN_AU_HEADER_SIZE, f) != MIN_AU_HEADER_SIZE) {
ast_log(LOG_WARNING, "Read failed (header)\n"); ast_log(LOG_WARNING, "Read failed (header)\n");
return -1; return -1;
} }
...@@ -285,8 +292,8 @@ static int check_header(FILE *f) ...@@ -285,8 +292,8 @@ static int check_header(FILE *f)
ast_log(LOG_WARNING, "Bad magic: 0x%x\n", magic); ast_log(LOG_WARNING, "Bad magic: 0x%x\n", magic);
} }
hdr_size = ltohl(header[AU_HDR_HDR_SIZE_OFF]); hdr_size = ltohl(header[AU_HDR_HDR_SIZE_OFF]);
if (hdr_size < AU_HEADER_SIZE) { if (hdr_size < MIN_AU_HEADER_SIZE) {
hdr_size = AU_HEADER_SIZE; hdr_size = MIN_AU_HEADER_SIZE;
} }
/* data_size = ltohl(header[AU_HDR_DATA_SIZE_OFF]); */ /* data_size = ltohl(header[AU_HDR_DATA_SIZE_OFF]); */
encoding = ltohl(header[AU_HDR_ENCODING_OFF]); encoding = ltohl(header[AU_HDR_ENCODING_OFF]);
...@@ -311,20 +318,26 @@ static int check_header(FILE *f) ...@@ -311,20 +318,26 @@ static int check_header(FILE *f)
ast_log(LOG_WARNING, "Failed to skip to data: %u\n", hdr_size); ast_log(LOG_WARNING, "Failed to skip to data: %u\n", hdr_size);
return -1; return -1;
} }
/* We'll need this later */
desc->hdr_size = hdr_size;
return data_size; return data_size;
} }
static int update_header(FILE *f) static int update_header(struct ast_filestream *fs)
{ {
off_t cur, end; off_t cur, end;
uint32_t datalen; uint32_t datalen;
int bytes; int bytes;
struct au_desc *desc = fs->_private;
FILE *f = fs->f;
cur = ftell(f); cur = ftell(f);
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
end = ftell(f); end = ftell(f);
/* data starts 24 bytes in */ /* data starts 24 bytes in */
bytes = end - AU_HEADER_SIZE; bytes = end - desc->hdr_size;
datalen = htoll(bytes); datalen = htoll(bytes);
if (cur < 0) { if (cur < 0) {
...@@ -346,12 +359,15 @@ static int update_header(FILE *f) ...@@ -346,12 +359,15 @@ static int update_header(FILE *f)
return 0; return 0;
} }
static int write_header(FILE *f) static int write_header(struct ast_filestream *fs)
{ {
struct au_desc *desc = fs->_private;
FILE *f = fs->f;
AU_HEADER(header); AU_HEADER(header);
header[AU_HDR_MAGIC_OFF] = htoll((uint32_t) AU_MAGIC); header[AU_HDR_MAGIC_OFF] = htoll((uint32_t) AU_MAGIC);
header[AU_HDR_HDR_SIZE_OFF] = htoll(AU_HEADER_SIZE); header[AU_HDR_HDR_SIZE_OFF] = htoll(desc->hdr_size);
header[AU_HDR_DATA_SIZE_OFF] = 0; header[AU_HDR_DATA_SIZE_OFF] = 0;
header[AU_HDR_ENCODING_OFF] = htoll(AU_ENC_8BIT_ULAW); header[AU_HDR_ENCODING_OFF] = htoll(AU_ENC_8BIT_ULAW);
header[AU_HDR_SAMPLE_RATE_OFF] = htoll(DEFAULT_SAMPLE_RATE); header[AU_HDR_SAMPLE_RATE_OFF] = htoll(DEFAULT_SAMPLE_RATE);
...@@ -359,7 +375,7 @@ static int write_header(FILE *f) ...@@ -359,7 +375,7 @@ static int write_header(FILE *f)
/* Write an au header, ignoring sizes which will be filled in later */ /* Write an au header, ignoring sizes which will be filled in later */
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);
if (fwrite(header, 1, AU_HEADER_SIZE, f) != AU_HEADER_SIZE) { if (fwrite(header, 1, MIN_AU_HEADER_SIZE, f) != MIN_AU_HEADER_SIZE) {
ast_log(LOG_WARNING, "Unable to write header\n"); ast_log(LOG_WARNING, "Unable to write header\n");
return -1; return -1;
} }
...@@ -368,14 +384,18 @@ static int write_header(FILE *f) ...@@ -368,14 +384,18 @@ static int write_header(FILE *f)
static int au_open(struct ast_filestream *s) static int au_open(struct ast_filestream *s)
{ {
if (check_header(s->f) < 0) if (check_header(s) < 0)
return -1; return -1;
return 0; return 0;
} }
static int au_rewrite(struct ast_filestream *s, const char *comment) static int au_rewrite(struct ast_filestream *s, const char *comment)
{ {
if (write_header(s->f)) struct au_desc *desc = s->_private;
desc->hdr_size = MIN_AU_HEADER_SIZE;
if (write_header(s))
return -1; return -1;
return 0; return 0;
} }
...@@ -383,8 +403,11 @@ static int au_rewrite(struct ast_filestream *s, const char *comment) ...@@ -383,8 +403,11 @@ static int au_rewrite(struct ast_filestream *s, const char *comment)
/* XXX check this, probably incorrect */ /* XXX check this, probably incorrect */
static int au_seek(struct ast_filestream *fs, off_t sample_offset, int whence) static int au_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
{ {
off_t min = AU_HEADER_SIZE, max, cur; off_t min, max, cur;
long offset = 0, bytes; long offset = 0, bytes;
struct au_desc *desc = fs->_private;
min = desc->hdr_size;
if (ast_format_cmp(fs->fmt->format, ast_format_g722) == AST_FORMAT_CMP_EQUAL) if (ast_format_cmp(fs->fmt->format, ast_format_g722) == AST_FORMAT_CMP_EQUAL)
bytes = sample_offset / 2; bytes = sample_offset / 2;
...@@ -440,13 +463,14 @@ static int au_trunc(struct ast_filestream *fs) ...@@ -440,13 +463,14 @@ static int au_trunc(struct ast_filestream *fs)
if (ftruncate(fd, cur)) { if (ftruncate(fd, cur)) {
return -1; return -1;
} }
return update_header(fs->f); return update_header(fs);
} }
static off_t au_tell(struct ast_filestream *fs) static off_t au_tell(struct ast_filestream *fs)
{ {
struct au_desc *desc = fs->_private;
off_t offset = ftello(fs->f); off_t offset = ftello(fs->f);
return offset - AU_HEADER_SIZE; return offset - desc->hdr_size;
} }
static struct ast_format_def alaw_f = { static struct ast_format_def alaw_f = {
...@@ -498,6 +522,7 @@ static struct ast_format_def au_f = { ...@@ -498,6 +522,7 @@ static struct ast_format_def au_f = {
.tell = au_tell, .tell = au_tell,
.read = pcm_read, .read = pcm_read,
.buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET, /* this many shorts */ .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET, /* this many shorts */
.desc_size = sizeof(struct au_desc),
}; };
static int unload_module(void) static int unload_module(void)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment