diff options
Diffstat (limited to 'apps/metadata')
-rw-r--r-- | apps/metadata/aiff.c | 23 | ||||
-rw-r--r-- | apps/metadata/wave.c | 138 |
2 files changed, 132 insertions, 29 deletions
diff --git a/apps/metadata/aiff.c b/apps/metadata/aiff.c index 67fb43b8c6..aba327f8c8 100644 --- a/apps/metadata/aiff.c +++ b/apps/metadata/aiff.c | |||
@@ -29,6 +29,9 @@ | |||
29 | #include "metadata_common.h" | 29 | #include "metadata_common.h" |
30 | #include "metadata_parsers.h" | 30 | #include "metadata_parsers.h" |
31 | 31 | ||
32 | /* compressionType: AIFC QuickTime IMA ADPCM */ | ||
33 | #define AIFC_FORMAT_QT_IMA_ADPCM "ima4" | ||
34 | |||
32 | bool get_aiff_metadata(int fd, struct mp3entry* id3) | 35 | bool get_aiff_metadata(int fd, struct mp3entry* id3) |
33 | { | 36 | { |
34 | /* Use the trackname part of the id3 structure as a temporary buffer */ | 37 | /* Use the trackname part of the id3 structure as a temporary buffer */ |
@@ -40,6 +43,7 @@ bool get_aiff_metadata(int fd, struct mp3entry* id3) | |||
40 | unsigned long numbytes = 0; | 43 | unsigned long numbytes = 0; |
41 | int read_bytes; | 44 | int read_bytes; |
42 | int i; | 45 | int i; |
46 | bool is_aifc = false; | ||
43 | 47 | ||
44 | if ((lseek(fd, 0, SEEK_SET) < 0) | 48 | if ((lseek(fd, 0, SEEK_SET) < 0) |
45 | || ((read_bytes = read(fd, buf, sizeof(id3->path))) < 54)) | 49 | || ((read_bytes = read(fd, buf, sizeof(id3->path))) < 54)) |
@@ -47,10 +51,15 @@ bool get_aiff_metadata(int fd, struct mp3entry* id3) | |||
47 | return false; | 51 | return false; |
48 | } | 52 | } |
49 | 53 | ||
50 | if ((memcmp(buf, "FORM",4) != 0) | 54 | if (memcmp(buf, "FORM",4) != 0) |
51 | || ((memcmp(&buf[8], "AIFF", 4) !=0) && (memcmp(&buf[8], "AIFC", 4) !=0))) | ||
52 | { | ||
53 | return false; | 55 | return false; |
56 | |||
57 | if (memcmp(&buf[8], "AIFF", 4) != 0) | ||
58 | { | ||
59 | if (memcmp(&buf[8], "AIFC", 4) != 0) | ||
60 | return false; | ||
61 | |||
62 | is_aifc = true; | ||
54 | } | 63 | } |
55 | 64 | ||
56 | buf += 12; | 65 | buf += 12; |
@@ -75,7 +84,13 @@ bool get_aiff_metadata(int fd, struct mp3entry* id3) | |||
75 | /* save format infos */ | 84 | /* save format infos */ |
76 | id3->bitrate = (sampleSize * numChannels * sampleRate) / 1000; | 85 | id3->bitrate = (sampleSize * numChannels * sampleRate) / 1000; |
77 | id3->frequency = sampleRate; | 86 | id3->frequency = sampleRate; |
78 | id3->length = ((int64_t) numSampleFrames * 1000) / id3->frequency; | 87 | if (!is_aifc || memcmp(&buf[26], AIFC_FORMAT_QT_IMA_ADPCM, 4) != 0) |
88 | id3->length = ((int64_t) numSampleFrames * 1000) / id3->frequency; | ||
89 | else | ||
90 | { | ||
91 | /* QuickTime IMA ADPCM is 1block = 64 data for each channel */ | ||
92 | id3->length = (int64_t)(numSampleFrames * 64000LL) / id3->frequency; | ||
93 | } | ||
79 | 94 | ||
80 | id3->vbr = false; /* AIFF files are CBR */ | 95 | id3->vbr = false; /* AIFF files are CBR */ |
81 | id3->filesize = filesize(fd); | 96 | id3->filesize = filesize(fd); |
diff --git a/apps/metadata/wave.c b/apps/metadata/wave.c index acef32dd38..79bb8178bd 100644 --- a/apps/metadata/wave.c +++ b/apps/metadata/wave.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "metadata.h" | 28 | #include "metadata.h" |
29 | #include "metadata_common.h" | 29 | #include "metadata_common.h" |
30 | #include "metadata_parsers.h" | 30 | #include "metadata_parsers.h" |
31 | #include "logf.h" | ||
31 | 32 | ||
32 | # define AV_WL32(p, d) do { \ | 33 | # define AV_WL32(p, d) do { \ |
33 | ((uint8_t*)(p))[0] = (d); \ | 34 | ((uint8_t*)(p))[0] = (d); \ |
@@ -40,29 +41,101 @@ | |||
40 | ((uint8_t*)(p))[1] = (d)>>8; \ | 41 | ((uint8_t*)(p))[1] = (d)>>8; \ |
41 | } while(0) | 42 | } while(0) |
42 | 43 | ||
44 | enum | ||
45 | { | ||
46 | WAVE_FORMAT_PCM = 0x0001, /* Microsoft PCM Format */ | ||
47 | WAVE_FORMAT_ADPCM = 0x0002, /* Microsoft ADPCM Format */ | ||
48 | WAVE_FORMAT_IEEE_FLOAT = 0x0003, /* IEEE Float */ | ||
49 | WAVE_FORMAT_ALAW = 0x0006, /* Microsoft ALAW */ | ||
50 | WAVE_FORMAT_MULAW = 0x0007, /* Microsoft MULAW */ | ||
51 | WAVE_FORMAT_DVI_ADPCM = 0x0011, /* Intel's DVI ADPCM */ | ||
52 | WAVE_FORMAT_DIALOGIC_OKI_ADPCM = 0x0017, /* Dialogic OKI ADPCM */ | ||
53 | WAVE_FORMAT_YAMAHA_ADPCM = 0x0020, /* Yamaha ADPCM */ | ||
54 | WAVE_FORMAT_XBOX_ADPCM = 0x0069, /* XBOX ADPCM */ | ||
55 | IBM_FORMAT_MULAW = 0x0101, /* same as WAVE_FORMAT_MULAW */ | ||
56 | IBM_FORMAT_ALAW = 0x0102, /* same as WAVE_FORMAT_ALAW */ | ||
57 | WAVE_FORMAT_ATRAC3 = 0x0270, /* Atrac3 stream */ | ||
58 | WAVE_FORMAT_SWF_ADPCM = 0x5346, /* Adobe SWF ADPCM */ | ||
59 | }; | ||
60 | |||
61 | struct wave_fmt { | ||
62 | unsigned int formattag; | ||
63 | unsigned long channels; | ||
64 | unsigned int blockalign; | ||
65 | unsigned long bitspersample; | ||
66 | unsigned int samplesperblock; | ||
67 | unsigned long numbytes; | ||
68 | }; | ||
69 | |||
70 | static unsigned long get_totalsamples(struct wave_fmt *fmt, struct mp3entry* id3) | ||
71 | { | ||
72 | unsigned long totalsamples = 0; | ||
73 | |||
74 | switch (fmt->formattag) | ||
75 | { | ||
76 | case WAVE_FORMAT_PCM: | ||
77 | case WAVE_FORMAT_IEEE_FLOAT: | ||
78 | case WAVE_FORMAT_ALAW: | ||
79 | case WAVE_FORMAT_MULAW: | ||
80 | case IBM_FORMAT_ALAW: | ||
81 | case IBM_FORMAT_MULAW: | ||
82 | totalsamples = | ||
83 | fmt->numbytes / ((((fmt->bitspersample - 1) / 8) + 1) * fmt->channels); | ||
84 | break; | ||
85 | case WAVE_FORMAT_ADPCM: | ||
86 | case WAVE_FORMAT_DVI_ADPCM: | ||
87 | case WAVE_FORMAT_XBOX_ADPCM: | ||
88 | totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock; | ||
89 | break; | ||
90 | case WAVE_FORMAT_YAMAHA_ADPCM: | ||
91 | if (fmt->samplesperblock == 0) | ||
92 | { | ||
93 | if (fmt->blockalign == ((id3->frequency / 60) + 4) * fmt->channels) | ||
94 | fmt->samplesperblock = id3->frequency / 30; | ||
95 | else | ||
96 | fmt->samplesperblock = fmt->blockalign * 2 / fmt->channels; | ||
97 | } | ||
98 | totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock; | ||
99 | break; | ||
100 | case WAVE_FORMAT_DIALOGIC_OKI_ADPCM: | ||
101 | totalsamples = 2 * fmt->numbytes; | ||
102 | break; | ||
103 | case WAVE_FORMAT_SWF_ADPCM: | ||
104 | if (fmt->samplesperblock == 0) | ||
105 | fmt->samplesperblock = (((fmt->blockalign << 3) - 2) / fmt->channels - 22) | ||
106 | / fmt->bitspersample; | ||
107 | |||
108 | totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock; | ||
109 | break; | ||
110 | default: | ||
111 | totalsamples = 0; | ||
112 | break; | ||
113 | } | ||
114 | return totalsamples; | ||
115 | } | ||
116 | |||
43 | bool get_wave_metadata(int fd, struct mp3entry* id3) | 117 | bool get_wave_metadata(int fd, struct mp3entry* id3) |
44 | { | 118 | { |
45 | /* Use the trackname part of the id3 structure as a temporary buffer */ | 119 | /* Use the trackname part of the id3 structure as a temporary buffer */ |
46 | unsigned char* buf = (unsigned char *)id3->path; | 120 | unsigned char* buf = (unsigned char *)id3->path; |
121 | struct wave_fmt fmt; | ||
47 | unsigned long totalsamples = 0; | 122 | unsigned long totalsamples = 0; |
48 | unsigned long channels = 0; | ||
49 | unsigned long bitspersample = 0; | ||
50 | unsigned long numbytes = 0; | ||
51 | unsigned long offset = 0; | 123 | unsigned long offset = 0; |
52 | int read_bytes; | 124 | int read_bytes; |
53 | int i; | 125 | int i; |
54 | 126 | ||
127 | memset(&fmt, 0, sizeof(struct wave_fmt)); | ||
128 | |||
55 | /* get RIFF chunk header */ | 129 | /* get RIFF chunk header */ |
56 | if ((lseek(fd, 0, SEEK_SET) < 0) | 130 | if ((lseek(fd, 0, SEEK_SET) < 0) || (read(fd, buf, 12) < 12)) |
57 | || ((read_bytes = read(fd, buf, 12)) < 12)) | ||
58 | { | 131 | { |
59 | return false; | 132 | return false; |
60 | } | 133 | } |
61 | offset += 12; | 134 | offset += 12; |
62 | 135 | ||
63 | if ((memcmp(buf, "RIFF",4) != 0) | 136 | if ((memcmp(buf, "RIFF", 4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0)) |
64 | || (memcmp(&buf[8], "WAVE", 4) !=0 )) | ||
65 | { | 137 | { |
138 | DEBUGF("metadata error: missing riff header.\n"); | ||
66 | return false; | 139 | return false; |
67 | } | 140 | } |
68 | 141 | ||
@@ -70,7 +143,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3) | |||
70 | while (true) | 143 | while (true) |
71 | { | 144 | { |
72 | /* get chunk header */ | 145 | /* get chunk header */ |
73 | if ((read_bytes = read(fd, buf, 8)) < 8) | 146 | if (read(fd, buf, 8) < 8) |
74 | return false; | 147 | return false; |
75 | offset += 8; | 148 | offset += 8; |
76 | 149 | ||
@@ -80,26 +153,41 @@ bool get_wave_metadata(int fd, struct mp3entry* id3) | |||
80 | if (memcmp(buf, "fmt ", 4) == 0) | 153 | if (memcmp(buf, "fmt ", 4) == 0) |
81 | { | 154 | { |
82 | /* get rest of chunk */ | 155 | /* get rest of chunk */ |
83 | if ((read_bytes = read(fd, buf, 16)) < 16) | 156 | if (i < 16) |
84 | return false; | 157 | return false; |
85 | offset += 16; | ||
86 | i -= 16; | ||
87 | 158 | ||
159 | read_bytes = 16; | ||
160 | if (i > 19) | ||
161 | read_bytes = 20; | ||
88 | 162 | ||
89 | /* skipping wFormatTag */ | 163 | if (read(fd, buf, read_bytes) != read_bytes) |
164 | return false; | ||
165 | |||
166 | offset += read_bytes; | ||
167 | i -= read_bytes; | ||
168 | |||
169 | /* wFormatTag */ | ||
170 | fmt.formattag = buf[0] | (buf[1] << 8); | ||
90 | /* wChannels */ | 171 | /* wChannels */ |
91 | channels = buf[2] | (buf[3] << 8); | 172 | fmt.channels = buf[2] | (buf[3] << 8); |
92 | /* dwSamplesPerSec */ | 173 | /* dwSamplesPerSec */ |
93 | id3->frequency = get_long_le(&buf[4]); | 174 | id3->frequency = get_long_le(&buf[4]); |
94 | /* dwAvgBytesPerSec */ | 175 | /* dwAvgBytesPerSec */ |
95 | id3->bitrate = (get_long_le(&buf[8]) * 8) / 1000; | 176 | id3->bitrate = (get_long_le(&buf[8]) * 8) / 1000; |
96 | /* wBlockAlign */ | 177 | /* wBlockAlign */ |
97 | id3->bytesperframe = buf[12] | (buf[13] << 8); | 178 | fmt.blockalign = buf[12] | (buf[13] << 8); |
179 | id3->bytesperframe = fmt.blockalign; | ||
98 | /* wBitsPerSample */ | 180 | /* wBitsPerSample */ |
99 | bitspersample = buf[14] | (buf[15] << 8); | 181 | fmt.bitspersample = buf[14] | (buf[15] << 8); |
182 | if (read_bytes > 19) | ||
183 | { | ||
184 | /* wSamplesPerBlock */ | ||
185 | fmt.samplesperblock = buf[18] | (buf[19] << 8); | ||
186 | } | ||
187 | |||
100 | /* Check for ATRAC3 stream */ | 188 | /* Check for ATRAC3 stream */ |
101 | if((buf[0] | (buf[1] << 8)) == 0x0270) | 189 | if (fmt.formattag == WAVE_FORMAT_ATRAC3) |
102 | { | 190 | { |
103 | int jsflag = 0; | 191 | int jsflag = 0; |
104 | if(id3->bitrate == 66 || id3->bitrate == 94) | 192 | if(id3->bitrate == 66 || id3->bitrate == 94) |
105 | jsflag = 1; | 193 | jsflag = 1; |
@@ -107,7 +195,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3) | |||
107 | id3->extradata_size = 14; | 195 | id3->extradata_size = 14; |
108 | id3->channels = 2; | 196 | id3->channels = 2; |
109 | id3->codectype = AFMT_OMA_ATRAC3; | 197 | id3->codectype = AFMT_OMA_ATRAC3; |
110 | /* Store the extradata for the codec */ | 198 | /* Store the extradata for the codec */ |
111 | AV_WL16(&id3->id3v2buf[0], 1); // always 1 | 199 | AV_WL16(&id3->id3v2buf[0], 1); // always 1 |
112 | AV_WL32(&id3->id3v2buf[2], id3->frequency); // samples rate | 200 | AV_WL32(&id3->id3v2buf[2], id3->frequency); // samples rate |
113 | AV_WL16(&id3->id3v2buf[6], jsflag); // coding mode | 201 | AV_WL16(&id3->id3v2buf[6], jsflag); // coding mode |
@@ -118,8 +206,9 @@ bool get_wave_metadata(int fd, struct mp3entry* id3) | |||
118 | } | 206 | } |
119 | else if (memcmp(buf, "data", 4) == 0) | 207 | else if (memcmp(buf, "data", 4) == 0) |
120 | { | 208 | { |
121 | numbytes = i; | 209 | fmt.numbytes = i; |
122 | id3->first_frame_offset = offset; | 210 | if (fmt.formattag == WAVE_FORMAT_ATRAC3) |
211 | id3->first_frame_offset = offset; | ||
123 | break; | 212 | break; |
124 | } | 213 | } |
125 | else if (memcmp(buf, "fact", 4) == 0) | 214 | else if (memcmp(buf, "fact", 4) == 0) |
@@ -128,7 +217,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3) | |||
128 | if (i >= 4) | 217 | if (i >= 4) |
129 | { | 218 | { |
130 | /* get rest of chunk */ | 219 | /* get rest of chunk */ |
131 | if ((read_bytes = read(fd, buf, 4)) < 4) | 220 | if (read(fd, buf, 4) < 4) |
132 | return false; | 221 | return false; |
133 | offset += 4; | 222 | offset += 4; |
134 | i -= 4; | 223 | i -= 4; |
@@ -145,16 +234,15 @@ bool get_wave_metadata(int fd, struct mp3entry* id3) | |||
145 | offset += i; | 234 | offset += i; |
146 | } | 235 | } |
147 | 236 | ||
148 | if ((numbytes == 0) || (channels == 0)) | 237 | if ((fmt.numbytes == 0) || (fmt.channels == 0) || (fmt.blockalign == 0)) |
149 | { | 238 | { |
239 | DEBUGF("metadata error: numbytes, channels, or blockalign is 0.\n"); | ||
150 | return false; | 240 | return false; |
151 | } | 241 | } |
152 | 242 | ||
153 | if (totalsamples == 0) | 243 | if (totalsamples == 0) |
154 | { | 244 | { |
155 | /* for PCM only */ | 245 | totalsamples = get_totalsamples(&fmt, id3); |
156 | totalsamples = numbytes | ||
157 | / ((((bitspersample - 1) / 8) + 1) * channels); | ||
158 | } | 246 | } |
159 | 247 | ||
160 | id3->vbr = false; /* All WAV files are CBR */ | 248 | id3->vbr = false; /* All WAV files are CBR */ |