1 /*
2 ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
3 ** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 **
19 ** Any non-GPL usage of this software or parts of this software is strictly
20 ** forbidden.
21 **
22 ** Commercial non-GPL licensing of this software is possible.
23 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
24 **
25 ** $Id: QCDMp4.c,v 1.4 2003/12/06 04:24:17 rjamorim Exp $
26 **/
27
28 //#define DEBUG_OUTPUT
29
30 #define WIN32_LEAN_AND_MEAN
31 #include <windows.h>
32 #include <commctrl.h>
33 #include <commdlg.h>
34 #include <stdlib.h>
35 #include <math.h>
36 #include <faad.h>
37 #include <mp4.h>
38
39 #include "resource.h"
40 #include "QCDInputDLL.h"
41 #include "utils.h"
42 #include "config.h"
43 //#include "aacinfo.h"
44 //#include "aac2mp4.h"
45 //
46 //const char *long_ext_list = "MP4\0MPEG-4 Files (*.MP4)\0M4A\0MPEG-4 Files (*.M4A)\0AAC\0AAC Files (*.AAC)\0";
47 //const char *short_ext_list = "MP4\0MPEG-4 Files (*.MP4)\0M4A\0MPEG-4 Files (*.M4A)\0";
48
49 static long priority_table[] = {
50 0,
51 THREAD_PRIORITY_HIGHEST,
52 THREAD_PRIORITY_ABOVE_NORMAL,
53 THREAD_PRIORITY_NORMAL,
54 THREAD_PRIORITY_BELOW_NORMAL,
55 THREAD_PRIORITY_LOWEST
56 };
57 static int res_id_table[] = {
58 IDC_16BITS,
59 IDC_24BITS,
60 IDC_32BITS,
61 0,
62 0,
63 /*IDC_16BITS_DITHERED*/ IDC_16BITS /* temp hack */
64 };
65 static int res_table[] = {
66 16,
67 24,
68 32,
69 0,
70 0,
71 16
72 };
73 //static char info_fn[_MAX_PATH];
74 //
75 //// post this to the main window at end of file (after playback has stopped)
76 //#define WM_WA_AAC_EOF WM_USER+2
77
78 struct seek_list
79 {
80 struct seek_list *next;
81 __int64 offset;
82 };
83
84 typedef struct state
85 {
86 /* general stuff */
87 faacDecHandle hDecoder;
88 int samplerate;
89 unsigned char channels;
90 double decode_pos_ms; // current decoding position, in milliseconds
91 int paused; // are we paused?
92 int seek_needed; // if != -1, it is the point that the decode thread should seek to, in ms.
93 char filename[_MAX_PATH];
94 int filetype; /* 0: MP4; 1: AAC */
95 int last_frame;
96 __int64 last_offset;
97
98 /* MP4 stuff */
99 MP4FileHandle mp4file;
100 int mp4track;
101 MP4SampleId numSamples;
102 MP4SampleId sampleId;
103
104 /* AAC stuff */
105 FILE *aacfile;
106 long m_aac_bytes_into_buffer;
107 long m_aac_bytes_consumed;
108 __int64 m_file_offset;
109 unsigned char *m_aac_buffer;
110 int m_at_eof;
111 double cur_pos_sec;
112 int m_header_type;
113 struct seek_list *m_head;
114 struct seek_list *m_tail;
115 unsigned long m_length;
116
117 /* for gapless decoding */
118 unsigned int useAacLength;
119 unsigned int framesize;
120 unsigned int initial;
121 unsigned long timescale;
122 } state;
123
124 static state mp4state;
125
126 //static In_Module module; // the output module (declared near the bottom of this file)
127 struct {
128 HINSTANCE hDllInstance;
129 HWND hMainWindow;
130 QCDModInitIn QCDCallbacks;
131 } module;
132 AudioInfo ai;
133
134 static int killPlayThread;
135 static int PlayThreadAlive = 0; // 1=play thread still running
136 HANDLE play_thread_handle = INVALID_HANDLE_VALUE; // the handle to the decode thread
137
138 /* Function definitions */
139 void *decode_aac_frame(state *st, faacDecFrameInfo *frameInfo);
140 DWORD WINAPI MP4PlayThread(void *b); // the decode thread procedure
141 DWORD WINAPI AACPlayThread(void *b); // the decode thread procedure
142
143
144 //typedef struct tag
145 //{
146 // char *item;
147 // char *value;
148 //} tag;
149 //
150 //typedef struct medialib_tags
151 //{
152 // struct tag *tags;
153 // unsigned int count;
154 //} medialib_tags;
155 //
156 //int tag_add_field(medialib_tags *tags, const char *item, const char *value)
157 //{
158 // void *backup = (void *)tags->tags;
159 //
160 // if (!item || (item && !*item) || !value) return 0;
161 //
162 // tags->tags = (struct tag *)realloc(tags->tags, (tags->count+1) * sizeof(tag));
163 // if (!tags->tags) {
164 // if (backup) free(backup);
165 // return 0;
166 // }
167 // else
168 // {
169 // int i_len = strlen(item);
170 // int v_len = strlen(value);
171 //
172 // tags->tags[tags->count].item = (char *)malloc(i_len+1);
173 // tags->tags[tags->count].value = (char *)malloc(v_len+1);
174 //
175 // if (!tags->tags[tags->count].item || !tags->tags[tags->count].value)
176 // {
177 // if (!tags->tags[tags->count].item) free (tags->tags[tags->count].item);
178 // if (!tags->tags[tags->count].value) free (tags->tags[tags->count].value);
179 // tags->tags[tags->count].item = NULL;
180 // tags->tags[tags->count].value = NULL;
181 // return 0;
182 // }
183 //
184 // memcpy(tags->tags[tags->count].item, item, i_len);
185 // memcpy(tags->tags[tags->count].value, value, v_len);
186 // tags->tags[tags->count].item[i_len] = '\0';
187 // tags->tags[tags->count].value[v_len] = '\0';
188 //
189 // tags->count++;
190 // return 1;
191 // }
192 //}
193 //
194 //int tag_set_field(medialib_tags *tags, const char *item, const char *value)
195 //{
196 // unsigned int i;
197 //
198 // if (!item || (item && !*item) || !value) return 0;
199 //
200 // for (i = 0; i < tags->count; i++)
201 // {
202 // if (!stricmp(tags->tags[i].item, item))
203 // {
204 // void *backup = (void *)tags->tags[i].value;
205 // int v_len = strlen(value);
206 //
207 // tags->tags[i].value = (char *)realloc(tags->tags[i].value, v_len+1);
208 // if (!tags->tags[i].value)
209 // {
210 // if (backup) free(backup);
211 // return 0;
212 // }
213 //
214 // memcpy(tags->tags[i].value, value, v_len);
215 // tags->tags[i].value[v_len] = '\0';
216 //
217 // return 1;
218 // }
219 // }
220 //
221 // return tag_add_field(tags, item, value);
222 //}
223 //
224 //int tag_delete(medialib_tags *tags)
225 //{
226 // unsigned int i;
227 //
228 // for (i = 0; i < tags->count; i++)
229 // {
230 // if (tags->tags[i].item) free(tags->tags[i].item);
231 // if (tags->tags[i].value) free(tags->tags[i].value);
232 // }
233 //
234 // if (tags->tags) free(tags->tags);
235 //
236 // tags->tags = NULL;
237 // tags->count = 0;
238 //}
239 //
240 //int ReadMP4Tag(MP4FileHandle file, medialib_tags *tags)
241 //{
242 // unsigned __int32 valueSize;
243 // unsigned __int8 *pValue;
244 // char *pName;
245 // unsigned int i = 0;
246 //
247 // do {
248 // pName = 0;
249 // pValue = 0;
250 // valueSize = 0;
251 //
252 // MP4GetMetadataByIndex(file, i, (const char **)&pName, &pValue, &valueSize);
253 //
254 // if (valueSize > 0)
255 // {
256 // char *val = (char *)malloc(valueSize+1);
257 // if (!val) return 0;
258 // memcpy(val, pValue, valueSize);
259 // val[valueSize] = '\0';
260 //
261 // if (pName[0] == '\xa9')
262 // {
263 // if (memcmp(pName, "�nam", 4) == 0)
264 // {
265 // tag_add_field(tags, "title", val);
266 // } else if (memcmp(pName, "�ART", 4) == 0) {
267 // tag_add_field(tags, "artist", val);
268 // } else if (memcmp(pName, "�wrt", 4) == 0) {
269 // tag_add_field(tags, "writer", val);
270 // } else if (memcmp(pName, "�alb", 4) == 0) {
271 // tag_add_field(tags, "album", val);
272 // } else if (memcmp(pName, "�day", 4) == 0) {
273 // tag_add_field(tags, "date", val);
274 // } else if (memcmp(pName, "�too", 4) == 0) {
275 // tag_add_field(tags, "tool", val);
276 // } else if (memcmp(pName, "�cmt", 4) == 0) {
277 // tag_add_field(tags, "comment", val);
278 // } else if (memcmp(pName, "�gen", 4) == 0) {
279 // tag_add_field(tags, "genre", val);
280 // } else {
281 // tag_add_field(tags, pName, val);
282 // }
283 // } else if (memcmp(pName, "gnre", 4) == 0) {
284 // char *t=0;
285 // if (MP4GetMetadataGenre(file, &t))
286 // {
287 // tag_add_field(tags, "genre", t);
288 // }
289 // } else if (memcmp(pName, "trkn", 4) == 0) {
290 // unsigned __int16 trkn = 0, tot = 0;
291 // char t[200];
292 // if (MP4GetMetadataTrack(file, &trkn, &tot))
293 // {
294 // if (tot > 0)
295 // wsprintf(t, "%d/%d", trkn, tot);
296 // else
297 // wsprintf(t, "%d", trkn);
298 // tag_add_field(tags, "tracknumber", t);
299 // }
300 // } else if (memcmp(pName, "disk", 4) == 0) {
301 // unsigned __int16 disk = 0, tot = 0;
302 // char t[200];
303 // if (MP4GetMetadataDisk(file, &disk, &tot))
304 // {
305 // if (tot > 0)
306 // wsprintf(t, "%d/%d", disk, tot);
307 // else
308 // wsprintf(t, "%d", disk);
309 // tag_add_field(tags, "disc", t);
310 // }
311 // } else if (memcmp(pName, "cpil", 4) == 0) {
312 // unsigned __int8 cpil = 0;
313 // char t[200];
314 // if (MP4GetMetadataCompilation(file, &cpil))
315 // {
316 // wsprintf(t, "%d", cpil);
317 // tag_add_field(tags, "compilation", t);
318 // }
319 // } else if (memcmp(pName, "tmpo", 4) == 0) {
320 // unsigned __int16 tempo = 0;
321 // char t[200];
322 // if (MP4GetMetadataTempo(file, &tempo))
323 // {
324 // wsprintf(t, "%d BPM", tempo);
325 // tag_add_field(tags, "tempo", t);
326 // }
327 // } else if (memcmp(pName, "NDFL", 4) == 0) {
328 // /* Removed */
329 // } else {
330 // tag_add_field(tags, pName, val);
331 // }
332 //
333 // free(val);
334 // }
335 //
336 // i++;
337 // } while (valueSize > 0);
338 //
339 // return 1;
340 //}
341 //
342 //int mp4_set_metadata(MP4FileHandle file, const char *item, const char *val)
343 //{
344 // if (!item || (item && !*item) || !val || (val && !*val)) return 0;
345 //
346 // if (!stricmp(item, "track") || !stricmp(item, "tracknumber"))
347 // {
348 // unsigned __int16 trkn, tot;
349 // int t1 = 0, t2 = 0;
350 // sscanf(val, "%d/%d", &t1, &t2);
351 // trkn = t1, tot = t2;
352 // if (!trkn) return 1;
353 // if (MP4SetMetadataTrack(file, trkn, tot)) return 1;
354 // }
355 // else if (!stricmp(item, "disc") || !stricmp(item, "disknumber"))
356 // {
357 // unsigned __int16 disk, tot;
358 // int t1 = 0, t2 = 0;
359 // sscanf(val, "%d/%d", &t1, &t2);
360 // disk = t1, tot = t2;
361 // if (!disk) return 1;
362 // if (MP4SetMetadataDisk(file, disk, tot)) return 1;
363 // }
364 // else if (!stricmp(item, "compilation"))
365 // {
366 // unsigned __int8 cpil = atoi(val);
367 // if (!cpil) return 1;
368 // if (MP4SetMetadataCompilation(file, cpil)) return 1;
369 // }
370 // else if (!stricmp(item, "tempo"))
371 // {
372 // unsigned __int16 tempo = atoi(val);
373 // if (!tempo) return 1;
374 // if (MP4SetMetadataTempo(file, tempo)) return 1;
375 // }
376 // else if (!stricmp(item, "artist"))
377 // {
378 // if (MP4SetMetadataArtist(file, val)) return 1;
379 // }
380 // else if (!stricmp(item, "writer"))
381 // {
382 // if (MP4SetMetadataWriter(file, val)) return 1;
383 // }
384 // else if (!stricmp(item, "title"))
385 // {
386 // if (MP4SetMetadataName(file, val)) return 1;
387 // }
388 // else if (!stricmp(item, "album"))
389 // {
390 // if (MP4SetMetadataAlbum(file, val)) return 1;
391 // }
392 // else if (!stricmp(item, "date") || !stricmp(item, "year"))
393 // {
394 // if (MP4SetMetadataYear(file, val)) return 1;
395 // }
396 // else if (!stricmp(item, "comment"))
397 // {
398 // if (MP4SetMetadataComment(file, val)) return 1;
399 // }
400 // else if (!stricmp(item, "genre"))
401 // {
402 // if (MP4SetMetadataGenre(file, val)) return 1;
403 // }
404 // else if (!stricmp(item, "tool"))
405 // {
406 // if (MP4SetMetadataTool(file, val)) return 1;
407 // }
408 // else
409 // {
410 // if (MP4SetMetadataFreeForm(file, (char *)item, (u_int8_t *)val, (u_int32_t)strlen(val))) return 1;
411 // }
412 //
413 // return 0;
414 //}
415 //
416 //int WriteMP4Tag(MP4FileHandle file, const medialib_tags *tags)
417 //{
418 // unsigned int i;
419 //
420 // for (i = 0; i < tags->count; i++)
421 // {
422 // const char *item = tags->tags[i].item;
423 // const char *value = tags->tags[i].value;
424 //
425 // if (value && *value)
426 // {
427 // mp4_set_metadata(file, item, value);
428 // }
429 // }
430 //}
431
432
433 #ifdef DEBUG_OUTPUT
in_mp4_DebugOutput(char * message)434 void in_mp4_DebugOutput(char *message)
435 {
436 char s[1024];
437
438 sprintf(s, "in_mp4: %s: %s", mp4state.filename, message);
439 OutputDebugString(s);
440 }
441 #endif
442
file_length(FILE * f)443 int file_length(FILE *f)
444 {
445 long end = 0;
446 long cur = ftell(f);
447 fseek(f, 0, SEEK_END);
448 end = ftell(f);
449 fseek(f, cur, SEEK_SET);
450
451 return end;
452 }
453
show_error(HWND hwnd,char * message,...)454 static void show_error(HWND hwnd, char *message, ...)
455 {
456 if (m_show_errors)
457 MessageBox(hwnd, message, "Error", MB_OK);
458 }
459
config_init()460 static void config_init()
461 {
462 //char *p=INI_FILE;
463 //GetModuleFileName(NULL,INI_FILE,_MAX_PATH);
464 //while (*p) p++;
465 //while (p >= INI_FILE && *p != '.') p--;
466 //strcpy(p+1,"ini");
467 module.QCDCallbacks.Service(opGetPluginSettingsFile, INI_FILE, MAX_PATH, 0);
468 }
469
config_read()470 void config_read()
471 {
472 char priority[10];
473 char resolution[10];
474 char show_errors[10];
475 char use_for_aac[10];
476 char downmix[10];
477 char vbr_display[10];
478
479 config_init();
480
481 strcpy(show_errors, "1");
482 strcpy(priority, "3");
483 strcpy(resolution, "0");
484 strcpy(use_for_aac, "1");
485 strcpy(downmix, "0");
486 strcpy(vbr_display, "1");
487 //strcpy(titleformat, "%7");
488
489 RS(priority);
490 RS(resolution);
491 RS(show_errors);
492 RS(use_for_aac);
493 RS(downmix);
494 RS(vbr_display);
495 //RS(titleformat);
496
497 m_priority = atoi(priority);
498 m_resolution = atoi(resolution);
499 m_show_errors = atoi(show_errors);
500 m_use_for_aac = atoi(use_for_aac);
501 m_downmix = atoi(downmix);
502 m_vbr_display = atoi(vbr_display);
503 }
504
config_write()505 void config_write()
506 {
507 char priority[10];
508 char resolution[10];
509 char show_errors[10];
510 char use_for_aac[10];
511 char downmix[10];
512 char vbr_display[10];
513
514 itoa(m_priority, priority, 10);
515 itoa(m_resolution, resolution, 10);
516 itoa(m_show_errors, show_errors, 10);
517 itoa(m_use_for_aac, use_for_aac, 10);
518 itoa(m_downmix, downmix, 10);
519 itoa(m_vbr_display, vbr_display, 10);
520
521 WS(priority);
522 WS(resolution);
523 WS(show_errors);
524 WS(use_for_aac);
525 WS(downmix);
526 WS(vbr_display);
527 //WS(titleformat);
528 }
529
Initialize(QCDModInfo * ModInfo,int flags)530 int Initialize(QCDModInfo *ModInfo, int flags)
531 {
532 ModInfo->moduleString = "MP4 Plug-in v" FAAD2_VERSION;
533
534 module.hMainWindow = (HWND)module.QCDCallbacks.Service(opGetParentWnd, 0, 0, 0);
535
536 // read config from config file
537 config_read();
538
539 ModInfo->moduleExtensions = !m_use_for_aac ? "MP4:M4A" : "MP4:M4A:AAC";
540
541 // return TRUE for successful initialization
542 return 1;
543 }
544
545 //----------------------------------------------------------------------------
546
ShutDown(int flags)547 void ShutDown(int flags)
548 {
549 Stop(mp4state.filename, STOPFLAG_FORCESTOP);
550 }
551
552 ///* Convert UNICODE to UTF-8
553 // Return number of bytes written */
554 //int unicodeToUtf8 ( const WCHAR* lpWideCharStr, char* lpMultiByteStr, int cwcChars )
555 //{
556 // const unsigned short* pwc = (unsigned short *)lpWideCharStr;
557 // unsigned char* pmb = (unsigned char *)lpMultiByteStr;
558 // const unsigned short* pwce;
559 // size_t cBytes = 0;
560 //
561 // if ( cwcChars >= 0 ) {
562 // pwce = pwc + cwcChars;
563 // } else {
564 // pwce = (unsigned short *)((size_t)-1);
565 // }
566 //
567 // while ( pwc < pwce ) {
568 // unsigned short wc = *pwc++;
569 //
570 // if ( wc < 0x00000080 ) {
571 // *pmb++ = (char)wc;
572 // cBytes++;
573 // } else
574 // if ( wc < 0x00000800 ) {
575 // *pmb++ = (char)(0xC0 | ((wc >> 6) & 0x1F));
576 // cBytes++;
577 // *pmb++ = (char)(0x80 | (wc & 0x3F));
578 // cBytes++;
579 // } else
580 // if ( wc < 0x00010000 ) {
581 // *pmb++ = (char)(0xE0 | ((wc >> 12) & 0x0F));
582 // cBytes++;
583 // *pmb++ = (char)(0x80 | ((wc >> 6) & 0x3F));
584 // cBytes++;
585 // *pmb++ = (char)(0x80 | (wc & 0x3F));
586 // cBytes++;
587 // }
588 // if ( wc == L'\0' )
589 // return cBytes;
590 // }
591 //
592 // return cBytes;
593 //}
594 //
595 ///* Convert UTF-8 coded string to UNICODE
596 // Return number of characters converted */
597 //int utf8ToUnicode ( const char* lpMultiByteStr, WCHAR* lpWideCharStr, int cmbChars )
598 //{
599 // const unsigned char* pmb = (unsigned char *)lpMultiByteStr;
600 // unsigned short* pwc = (unsigned short *)lpWideCharStr;
601 // const unsigned char* pmbe;
602 // size_t cwChars = 0;
603 //
604 // if ( cmbChars >= 0 ) {
605 // pmbe = pmb + cmbChars;
606 // } else {
607 // pmbe = (unsigned char *)((size_t)-1);
608 // }
609 //
610 // while ( pmb < pmbe ) {
611 // char mb = *pmb++;
612 // unsigned int cc = 0;
613 // unsigned int wc;
614 //
615 // while ( (cc < 7) && (mb & (1 << (7 - cc)))) {
616 // cc++;
617 // }
618 //
619 // if ( cc == 1 || cc > 6 ) // illegal character combination for UTF-8
620 // continue;
621 //
622 // if ( cc == 0 ) {
623 // wc = mb;
624 // } else {
625 // wc = (mb & ((1 << (7 - cc)) - 1)) << ((cc - 1) * 6);
626 // while ( --cc > 0 ) {
627 // if ( pmb == pmbe ) // reached end of the buffer
628 // return cwChars;
629 // mb = *pmb++;
630 // if ( ((mb >> 6) & 0x03) != 2 ) // not part of multibyte character
631 // return cwChars;
632 // wc |= (mb & 0x3F) << ((cc - 1) * 6);
633 // }
634 // }
635 //
636 // if ( wc & 0xFFFF0000 )
637 // wc = L'?';
638 // *pwc++ = wc;
639 // cwChars++;
640 // if ( wc == L'\0' )
641 // return cwChars;
642 // }
643 //
644 // return cwChars;
645 //}
646 //
647 ///* convert Windows ANSI to UTF-8 */
648 //int ConvertANSIToUTF8 ( const char* ansi, char* utf8 )
649 //{
650 // WCHAR* wszValue; // Unicode value
651 // size_t ansi_len;
652 // size_t len;
653 //
654 // *utf8 = '\0';
655 // if ( ansi == NULL )
656 // return 0;
657 //
658 // ansi_len = strlen ( ansi );
659 //
660 // if ( (wszValue = (WCHAR *)malloc ( (ansi_len + 1) * 2 )) == NULL )
661 // return 0;
662 //
663 // /* Convert ANSI value to Unicode */
664 // if ( (len = MultiByteToWideChar ( CP_ACP, 0, ansi, ansi_len + 1, wszValue, (ansi_len + 1) * 2 )) == 0 ) {
665 // free ( wszValue );
666 // return 0;
667 // }
668 //
669 // /* Convert Unicode value to UTF-8 */
670 // if ( (len = unicodeToUtf8 ( wszValue, utf8, -1 )) == 0 ) {
671 // free ( wszValue );
672 // return 0;
673 // }
674 //
675 // free ( wszValue );
676 //
677 // return len-1;
678 //}
679 //
680 ///* convert UTF-8 to Windows ANSI */
681 //int ConvertUTF8ToANSI ( const char* utf8, char* ansi )
682 //{
683 // WCHAR* wszValue; // Unicode value
684 // size_t utf8_len;
685 // size_t len;
686 //
687 // *ansi = '\0';
688 // if ( utf8 == NULL )
689 // return 0;
690 //
691 // utf8_len = strlen ( utf8 );
692 //
693 // if ( (wszValue = (WCHAR *)malloc ( (utf8_len + 1) * 2 )) == NULL )
694 // return 0;
695 //
696 // /* Convert UTF-8 value to Unicode */
697 // if ( (len = utf8ToUnicode ( utf8, wszValue, utf8_len + 1 )) == 0 ) {
698 // free ( wszValue );
699 // return 0;
700 // }
701 //
702 // /* Convert Unicode value to ANSI */
703 // if ( (len = WideCharToMultiByte ( CP_ACP, 0, wszValue, -1, ansi, (utf8_len + 1) * 2, NULL, NULL )) == 0 ) {
704 // free ( wszValue );
705 // return 0;
706 // }
707 //
708 // free ( wszValue );
709 //
710 // return len-1;
711 //}
712 //
713 //BOOL uSetDlgItemText(HWND hwnd, int id, const char *str)
714 //{
715 // char *temp;
716 // size_t len;
717 // int r;
718 //
719 // if (!str) return FALSE;
720 // if (!*str) return TRUE;
721 // len = strlen(str);
722 // temp = malloc(len+1);
723 // if (!temp) return FALSE;
724 // r = ConvertUTF8ToANSI(str, temp);
725 // if (r > 0)
726 // SetDlgItemText(hwnd, id, temp);
727 // free(temp);
728 //
729 // return r>0 ? TRUE : FALSE;
730 //}
731 //
732 //UINT uGetDlgItemText(HWND hwnd, int id, char *str, int max)
733 //{
734 // char *temp, *utf8;
735 // int len;
736 // HWND w;
737 //
738 // if (!str || !max) return 0;
739 // *str = '\0';
740 // w = GetDlgItem(hwnd, id);
741 // len = GetWindowTextLength(w);
742 // temp = malloc(len+1);
743 // if (!temp) return 0;
744 // utf8 = malloc((len+1)*4);
745 // if (!utf8)
746 // {
747 // free(temp);
748 // return 0;
749 // }
750 //
751 // len = GetWindowText(w, temp, len+1);
752 // if (len > 0)
753 // {
754 // len = ConvertANSIToUTF8(temp, utf8);
755 // if (len > max-1)
756 // {
757 // len = max-1;
758 // utf8[max] = '\0';
759 // }
760 // memcpy(str, utf8, len+1);
761 // }
762 //
763 // free(temp);
764 // free(utf8);
765 //
766 // return len;
767 //}
768 //
769 //BOOL CALLBACK mp4_info_dialog_proc(HWND hwndDlg, UINT message,
770 // WPARAM wParam, LPARAM lParam)
771 //{
772 // char *file_info;
773 // MP4FileHandle file;
774 // char *pVal, dummy1[1024], dummy3;
775 // short dummy, dummy2;
776 // char temp[1024];
777 // struct medialib_tags tags;
778 // tags.count = 0;
779 // tags.tags = NULL;
780 //
781 //#ifdef DEBUG_OUTPUT
782 // in_mp4_DebugOutput("mp4_info_dialog_proc");
783 //#endif
784 //
785 // switch (message) {
786 // case WM_INITDIALOG:
787 // EnableWindow(GetDlgItem(hwndDlg,IDC_CONVERT), FALSE);
788 // ShowWindow(GetDlgItem(hwndDlg,IDC_CONVERT), SW_HIDE);
789 // EnableWindow(GetDlgItem(hwndDlg,IDC_CONVERT1), FALSE);
790 // ShowWindow(GetDlgItem(hwndDlg,IDC_CONVERT1), SW_HIDE);
791 // EnableWindow(GetDlgItem(hwndDlg,IDC_CONVERT2), FALSE);
792 // ShowWindow(GetDlgItem(hwndDlg,IDC_CONVERT2), SW_HIDE);
793 //
794 // file = MP4Read(info_fn, 0);
795 //
796 // if (file == MP4_INVALID_FILE_HANDLE)
797 // return FALSE;
798 //
799 // file_info = MP4Info(file, MP4_INVALID_TRACK_ID);
800 // SetDlgItemText(hwndDlg, IDC_INFOTEXT, file_info);
801 // free(file_info);
802 //
803 // /* get Metadata */
804 //
805 // pVal = NULL;
806 // if (MP4GetMetadataName(file, &pVal))
807 // uSetDlgItemText(hwndDlg,IDC_METANAME, pVal);
808 //
809 // pVal = NULL;
810 // if (MP4GetMetadataArtist(file, &pVal))
811 // uSetDlgItemText(hwndDlg,IDC_METAARTIST, pVal);
812 //
813 // pVal = NULL;
814 // if (MP4GetMetadataWriter(file, &pVal))
815 // uSetDlgItemText(hwndDlg,IDC_METAWRITER, pVal);
816 //
817 // pVal = NULL;
818 // if (MP4GetMetadataComment(file, &pVal))
819 // uSetDlgItemText(hwndDlg,IDC_METACOMMENTS, pVal);
820 //
821 // pVal = NULL;
822 // if (MP4GetMetadataAlbum(file, &pVal))
823 // uSetDlgItemText(hwndDlg,IDC_METAALBUM, pVal);
824 //
825 // pVal = NULL;
826 // if (MP4GetMetadataGenre(file, &pVal))
827 // uSetDlgItemText(hwndDlg,IDC_METAGENRE, pVal);
828 //
829 // dummy = 0;
830 // MP4GetMetadataTempo(file, &dummy);
831 // if (dummy)
832 // {
833 // wsprintf(dummy1, "%d", dummy);
834 // SetDlgItemText(hwndDlg,IDC_METATEMPO, dummy1);
835 // }
836 //
837 // dummy = 0; dummy2 = 0;
838 // MP4GetMetadataTrack(file, &dummy, &dummy2);
839 // if (dummy)
840 // {
841 // wsprintf(dummy1, "%d", dummy);
842 // SetDlgItemText(hwndDlg,IDC_METATRACK1, dummy1);
843 // }
844 // if (dummy2)
845 // {
846 // wsprintf(dummy1, "%d", dummy2);
847 // SetDlgItemText(hwndDlg,IDC_METATRACK2, dummy1);
848 // }
849 //
850 // dummy = 0; dummy2 = 0;
851 // MP4GetMetadataDisk(file, &dummy, &dummy2);
852 // if (dummy)
853 // {
854 // wsprintf(dummy1, "%d", dummy);
855 // SetDlgItemText(hwndDlg,IDC_METADISK1, dummy1);
856 // }
857 // if (dummy2)
858 // {
859 // wsprintf(dummy1, "%d", dummy2);
860 // SetDlgItemText(hwndDlg,IDC_METADISK2, dummy1);
861 // }
862 //
863 // pVal = NULL;
864 // if (MP4GetMetadataYear(file, &pVal))
865 // uSetDlgItemText(hwndDlg,IDC_METAYEAR, pVal);
866 //
867 // dummy3 = 0;
868 // MP4GetMetadataCompilation(file, &dummy3);
869 // if (dummy3)
870 // SendMessage(GetDlgItem(hwndDlg, IDC_METACOMPILATION), BM_SETCHECK, BST_CHECKED, 0);
871 //
872 // /* ! Metadata */
873 //
874 // MP4Close(file);
875 //
876 // return TRUE;
877 //
878 // case WM_COMMAND:
879 // switch (LOWORD(wParam)) {
880 // case IDCANCEL:
881 // EndDialog(hwndDlg, wParam);
882 // return TRUE;
883 // case IDOK:
884 //
885 // /* save Metadata changes */
886 //
887 // tag_delete(&tags);
888 // file = MP4Read(info_fn, 0);
889 // if (file != MP4_INVALID_FILE_HANDLE)
890 // {
891 // ReadMP4Tag(file, &tags);
892 // MP4Close(file);
893 //
894 // file = MP4Modify(info_fn, 0, 0);
895 // if (file != MP4_INVALID_FILE_HANDLE)
896 // {
897 // MP4MetadataDelete(file);
898 // MP4Close(file);
899 // }
900 // }
901 //
902 // file = MP4Modify(info_fn, 0, 0);
903 // if (file == MP4_INVALID_FILE_HANDLE)
904 // {
905 // tag_delete(&tags);
906 // EndDialog(hwndDlg, wParam);
907 // return FALSE;
908 // }
909 //
910 // uGetDlgItemText(hwndDlg, IDC_METANAME, dummy1, 1024);
911 // tag_set_field(&tags, "title", dummy1);
912 //
913 // uGetDlgItemText(hwndDlg, IDC_METAWRITER, dummy1, 1024);
914 // tag_set_field(&tags, "writer", dummy1);
915 //
916 // uGetDlgItemText(hwndDlg, IDC_METAARTIST, dummy1, 1024);
917 // tag_set_field(&tags, "artist", dummy1);
918 //
919 // uGetDlgItemText(hwndDlg, IDC_METAALBUM, dummy1, 1024);
920 // tag_set_field(&tags, "album", dummy1);
921 //
922 // uGetDlgItemText(hwndDlg, IDC_METACOMMENTS, dummy1, 1024);
923 // tag_set_field(&tags, "comment", dummy1);
924 //
925 // uGetDlgItemText(hwndDlg, IDC_METAGENRE, dummy1, 1024);
926 // tag_set_field(&tags, "genre", dummy1);
927 //
928 // uGetDlgItemText(hwndDlg, IDC_METAYEAR, dummy1, 1024);
929 // tag_set_field(&tags, "year", dummy1);
930 //
931 // GetDlgItemText(hwndDlg, IDC_METATRACK1, dummy1, 1024);
932 // dummy = atoi(dummy1);
933 // GetDlgItemText(hwndDlg, IDC_METATRACK2, dummy1, 1024);
934 // dummy2 = atoi(dummy1);
935 // wsprintf(temp, "%d/%d", dummy, dummy2);
936 // tag_set_field(&tags, "track", temp);
937 //
938 // GetDlgItemText(hwndDlg, IDC_METADISK1, dummy1, 1024);
939 // dummy = atoi(dummy1);
940 // GetDlgItemText(hwndDlg, IDC_METADISK2, dummy1, 1024);
941 // dummy2 = atoi(dummy1);
942 // wsprintf(temp, "%d/%d", dummy, dummy2);
943 // tag_set_field(&tags, "disc", temp);
944 //
945 // GetDlgItemText(hwndDlg, IDC_METATEMPO, dummy1, 1024);
946 // tag_set_field(&tags, "tempo", dummy1);
947 //
948 // dummy3 = SendMessage(GetDlgItem(hwndDlg, IDC_METACOMPILATION), BM_GETCHECK, 0, 0);
949 // tag_set_field(&tags, "compilation", (dummy3 ? "1" : "0"));
950 //
951 // WriteMP4Tag(file, &tags);
952 //
953 // MP4Close(file);
954 //
955 // MP4Optimize(info_fn, NULL, 0);
956 // /* ! */
957 //
958 // EndDialog(hwndDlg, wParam);
959 // return TRUE;
960 // }
961 // }
962 // return FALSE;
963 //}
964 //
965 ///* returns the name of the object type */
966 //char *get_ot_string(int ot)
967 //{
968 // switch (ot)
969 // {
970 // case 0:
971 // return "Main";
972 // case 1:
973 // return "LC";
974 // case 2:
975 // return "SSR";
976 // case 3:
977 // return "LTP";
978 // }
979 // return NULL;
980 //}
981 //
982 //BOOL CALLBACK aac_info_dialog_proc(HWND hwndDlg, UINT message,
983 // WPARAM wParam, LPARAM lParam)
984 //{
985 // faadAACInfo aacInfo;
986 // char *info_text, *header_string;
987 //
988 //#ifdef DEBUG_OUTPUT
989 // in_mp4_DebugOutput("aac_info_dialog_proc");
990 //#endif
991 //
992 // switch (message) {
993 // case WM_INITDIALOG:
994 // EnableWindow(GetDlgItem(hwndDlg,IDC_USERDATA), FALSE) ;
995 // ShowWindow(GetDlgItem(hwndDlg,IDC_USERDATA), SW_HIDE);
996 //
997 // ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC1), SW_HIDE);
998 // ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC2), SW_HIDE);
999 // ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC3), SW_HIDE);
1000 // ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC4), SW_HIDE);
1001 // ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC5), SW_HIDE);
1002 // ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC6), SW_HIDE);
1003 // ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC7), SW_HIDE);
1004 // ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC8), SW_HIDE);
1005 // ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC9), SW_HIDE);
1006 // ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC10), SW_HIDE);
1007 // ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC11), SW_HIDE);
1008 // ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC12), SW_HIDE);
1009 //
1010 // ShowWindow(GetDlgItem(hwndDlg,IDC_METANAME), SW_HIDE);
1011 // ShowWindow(GetDlgItem(hwndDlg,IDC_METAARTIST), SW_HIDE);
1012 // ShowWindow(GetDlgItem(hwndDlg,IDC_METAWRITER), SW_HIDE);
1013 // ShowWindow(GetDlgItem(hwndDlg,IDC_METACOMMENTS), SW_HIDE);
1014 // ShowWindow(GetDlgItem(hwndDlg,IDC_METAALBUM), SW_HIDE);
1015 // ShowWindow(GetDlgItem(hwndDlg,IDC_METAGENRE), SW_HIDE);
1016 // ShowWindow(GetDlgItem(hwndDlg,IDC_METATEMPO), SW_HIDE);
1017 // ShowWindow(GetDlgItem(hwndDlg,IDC_METATRACK1), SW_HIDE);
1018 // ShowWindow(GetDlgItem(hwndDlg,IDC_METATRACK2), SW_HIDE);
1019 // ShowWindow(GetDlgItem(hwndDlg,IDC_METADISK1), SW_HIDE);
1020 // ShowWindow(GetDlgItem(hwndDlg,IDC_METADISK2), SW_HIDE);
1021 // ShowWindow(GetDlgItem(hwndDlg,IDC_METAYEAR), SW_HIDE);
1022 // ShowWindow(GetDlgItem(hwndDlg,IDC_METACOMPILATION), SW_HIDE);
1023 //
1024 // info_text = malloc(1024*sizeof(char));
1025 //
1026 // get_AAC_format(info_fn, &aacInfo);
1027 //
1028 // switch (aacInfo.headertype)
1029 // {
1030 // case 0: /* RAW */
1031 // header_string = " RAW";
1032 // break;
1033 // case 1: /* ADIF */
1034 // header_string = " ADIF";
1035 // break;
1036 // case 2: /* ADTS */
1037 // header_string = " ADTS";
1038 // break;
1039 // }
1040 //
1041 // sprintf(info_text, "%s AAC %s%s, %d sec, %d kbps, %d Hz",
1042 // (aacInfo.version==2)?"MPEG-2":"MPEG-4", get_ot_string(aacInfo.object_type),
1043 // header_string,
1044 // (int)((float)aacInfo.length/1000.0), (int)((float)aacInfo.bitrate/1000.0+0.5),
1045 // aacInfo.sampling_rate);
1046 //
1047 // SetDlgItemText(hwndDlg, IDC_INFOTEXT, info_text);
1048 //
1049 // free(info_text);
1050 //
1051 // return TRUE;
1052 //
1053 // case WM_COMMAND:
1054 // switch (LOWORD(wParam))
1055 // {
1056 // case IDC_CONVERT:
1057 // {
1058 // char mp4FileName[256];
1059 // char *extension;
1060 // OPENFILENAME ofn;
1061 //
1062 // lstrcpy(mp4FileName, info_fn);
1063 // extension = strrchr(mp4FileName, '.');
1064 // lstrcpy(extension, ".mp4");
1065 //
1066 // memset(&ofn, 0, sizeof(OPENFILENAME));
1067 // ofn.lStructSize = sizeof(OPENFILENAME);
1068 // ofn.hwndOwner = hwndDlg;
1069 // ofn.hInstance = module.hDllInstance;
1070 // ofn.nMaxFileTitle = 31;
1071 // ofn.lpstrFile = (LPSTR)mp4FileName;
1072 // ofn.nMaxFile = _MAX_PATH;
1073 // ofn.lpstrFilter = "MP4 Files (*.mp4)\0*.mp4\0";
1074 // ofn.lpstrDefExt = "mp4";
1075 // ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
1076 // ofn.lpstrTitle = "Select Output File";
1077 //
1078 // if (GetSaveFileName(&ofn))
1079 // {
1080 // if (covert_aac_to_mp4(info_fn, mp4FileName))
1081 // {
1082 // MessageBox(hwndDlg, "An error occured while converting AAC to MP4!", "An error occured!", MB_OK);
1083 // return FALSE;
1084 // }
1085 // }
1086 // return TRUE;
1087 // }
1088 // case IDCANCEL:
1089 // case IDOK:
1090 // EndDialog(hwndDlg, wParam);
1091 // return TRUE;
1092 // }
1093 // }
1094 // return FALSE;
1095 //}
1096 //
1097 //int infoDlg(char *fn, HWND hwndParent)
1098 //{
1099 // if(!stricmp(fn + strlen(fn) - 3,"AAC"))
1100 // {
1101 // lstrcpy(info_fn, fn);
1102 //
1103 // DialogBox(module.hDllInstance, MAKEINTRESOURCE(IDD_INFO),
1104 // hwndParent, aac_info_dialog_proc);
1105 // } else {
1106 // lstrcpy(info_fn, fn);
1107 //
1108 // DialogBox(module.hDllInstance, MAKEINTRESOURCE(IDD_INFO),
1109 // hwndParent, mp4_info_dialog_proc);
1110 // }
1111 //
1112 // return 0;
1113 //}
1114 //
1115 ///* Get the title from the file */
1116 //void ConstructTitle(MP4FileHandle file, char *filename, char *title, char *format)
1117 //{
1118 // char temp[4096];
1119 // int some_info = 0;
1120 // char *in = format;
1121 // char *out = temp;//title;
1122 // char *bound = out + sizeof(temp) - 256; //out + (MAX_PATH - 10 - 1);
1123 // char *pVal, dummy1[1024];
1124 // short dummy, dummy2;
1125 //
1126 // while (*in && out < bound)
1127 // {
1128 // switch (*in)
1129 // {
1130 // case '%':
1131 // ++in;
1132 // break;
1133 //
1134 // default:
1135 // *out++ = *in++;
1136 // continue;
1137 // }
1138 //
1139 // /* handle % escape sequence */
1140 // switch (*in++)
1141 // {
1142 // case '0':
1143 // dummy = 0; dummy2 = 0;
1144 // if (MP4GetMetadataTrack(file, &dummy, &dummy2))
1145 // {
1146 // out += wsprintf(out, "%d", (int)dummy);
1147 // some_info = 1;
1148 // }
1149 // break;
1150 //
1151 // case '1':
1152 // pVal = NULL;
1153 // if (MP4GetMetadataArtist(file, &pVal))
1154 // {
1155 // out += wsprintf(out, "%s", pVal);
1156 // some_info = 1;
1157 // }
1158 // break;
1159 //
1160 // case '2':
1161 // pVal = NULL;
1162 // if (MP4GetMetadataName(file, &pVal))
1163 // {
1164 // out += wsprintf(out, "%s", pVal);
1165 // some_info = 1;
1166 // }
1167 // break;
1168 //
1169 // case '3':
1170 // pVal = NULL;
1171 // if (MP4GetMetadataAlbum(file, &pVal))
1172 // {
1173 // out += wsprintf(out, "%s", pVal);
1174 // some_info = 1;
1175 // }
1176 // break;
1177 //
1178 // case '4':
1179 // pVal = NULL;
1180 // if (MP4GetMetadataYear(file, &pVal))
1181 // {
1182 // out += wsprintf(out, "%s", pVal);
1183 // some_info = 1;
1184 // }
1185 // break;
1186 //
1187 // case '5':
1188 // pVal = NULL;
1189 // if (MP4GetMetadataComment(file, &pVal))
1190 // {
1191 // out += wsprintf(out, "%s", pVal);
1192 // some_info = 1;
1193 // }
1194 // break;
1195 //
1196 // case '6':
1197 // pVal = NULL;
1198 // if (MP4GetMetadataGenre(file, &pVal))
1199 // {
1200 // out += wsprintf(out, "%s", pVal);
1201 // some_info = 1;
1202 // }
1203 // break;
1204 //
1205 // case '7':
1206 // {
1207 // const char *p=strrchr(filename,'\\');
1208 // if (!p) p=filename; else p++;
1209 // out += ConvertANSIToUTF8(p, out);
1210 // some_info = 1;
1211 // break;
1212 // }
1213 //
1214 // default:
1215 // break;
1216 // }
1217 // }
1218 //
1219 // *out = '\0';
1220 //
1221 // if (!some_info)
1222 // {
1223 // char *p=filename+lstrlen(filename);
1224 // while (*p != '\\' && p >= filename) p--;
1225 // lstrcpy(title,++p);
1226 // }
1227 // else
1228 // {
1229 // int len = ConvertUTF8ToANSI(temp, dummy1);
1230 // if (len > (MAX_PATH - 10 - 1)) len = (MAX_PATH - 10 - 1);
1231 // memcpy(title, dummy1, len);
1232 // title[len] = '\0';
1233 // }
1234 //}
1235
config_dialog_proc(HWND hwndDlg,UINT message,WPARAM wParam,LPARAM lParam)1236 BOOL CALLBACK config_dialog_proc(HWND hwndDlg, UINT message,
1237 WPARAM wParam, LPARAM lParam)
1238 {
1239 int i;
1240
1241 switch (message) {
1242 case WM_INITDIALOG:
1243 SendMessage(GetDlgItem(hwndDlg, IDC_PRIORITY), TBM_SETRANGE, TRUE, MAKELONG(1,5));
1244 SendMessage(GetDlgItem(hwndDlg, IDC_PRIORITY), TBM_SETPOS, TRUE, m_priority);
1245 SendMessage(GetDlgItem(hwndDlg, res_id_table[m_resolution]), BM_SETCHECK, BST_CHECKED, 0);
1246 if (m_show_errors)
1247 SendMessage(GetDlgItem(hwndDlg, IDC_ERROR), BM_SETCHECK, BST_CHECKED, 0);
1248 if (m_use_for_aac)
1249 SendMessage(GetDlgItem(hwndDlg, IDC_USEFORAAC), BM_SETCHECK, BST_CHECKED, 0);
1250 if (m_downmix)
1251 SendMessage(GetDlgItem(hwndDlg, IDC_DOWNMIX), BM_SETCHECK, BST_CHECKED, 0);
1252 if (m_vbr_display)
1253 SendMessage(GetDlgItem(hwndDlg, IDC_VBR), BM_SETCHECK, BST_CHECKED, 0);
1254 SetDlgItemText(hwndDlg, IDC_TITLEFORMAT, titleformat);
1255 return TRUE;
1256
1257 case WM_COMMAND:
1258 switch (LOWORD(wParam)) {
1259 case IDCANCEL:
1260 EndDialog(hwndDlg, wParam);
1261 return TRUE;
1262 case IDOK:
1263 m_show_errors = SendMessage(GetDlgItem(hwndDlg, IDC_ERROR), BM_GETCHECK, 0, 0);
1264 m_use_for_aac = SendMessage(GetDlgItem(hwndDlg, IDC_USEFORAAC), BM_GETCHECK, 0, 0);
1265 m_downmix = SendMessage(GetDlgItem(hwndDlg, IDC_DOWNMIX), BM_GETCHECK, 0, 0);
1266 m_vbr_display = SendMessage(GetDlgItem(hwndDlg, IDC_VBR), BM_GETCHECK, 0, 0);
1267 GetDlgItemText(hwndDlg, IDC_TITLEFORMAT, titleformat, MAX_PATH);
1268
1269 m_priority = SendMessage(GetDlgItem(hwndDlg, IDC_PRIORITY), TBM_GETPOS, 0, 0);
1270 for (i = 0; i < 6; i++)
1271 {
1272 if (SendMessage(GetDlgItem(hwndDlg, res_id_table[i]), BM_GETCHECK, 0, 0))
1273 {
1274 m_resolution = i;
1275 break;
1276 }
1277 }
1278
1279 /* save config */
1280 config_write();
1281
1282 //if (!m_use_for_aac)
1283 //{
1284 // module.FileExtensions = short_ext_list;
1285 //} else {
1286 // module.FileExtensions = long_ext_list;
1287 //}
1288
1289 EndDialog(hwndDlg, wParam);
1290 return TRUE;
1291 }
1292 }
1293 return FALSE;
1294 }
1295
Configure(int flags)1296 void Configure(int flags)
1297 {
1298 DialogBox(module.hDllInstance, MAKEINTRESOURCE(IDD_CONFIG),
1299 module.hMainWindow, config_dialog_proc);
1300 }
1301
1302 //-----------------------------------------------------------------------------
1303
About(int flags)1304 void About(int flags)
1305 {
1306 MessageBox(module.hMainWindow,
1307 "AudioCoding.com MPEG-4 General Audio player " FAAD2_VERSION " compiled on " __DATE__ ".\n"
1308 "Visit the website for more info.\n"
1309 "Ported to QCD by Shao Hao.\n"
1310 "Copyright 2002-2003 AudioCoding.com",
1311 "About",
1312 MB_OK);
1313 }
1314
1315 //-----------------------------------------------------------------------------
1316
fill_buffer(state * st)1317 int fill_buffer(state *st)
1318 {
1319 int bread;
1320
1321 if (st->m_aac_bytes_consumed > 0)
1322 {
1323 if (st->m_aac_bytes_into_buffer)
1324 {
1325 memmove((void*)st->m_aac_buffer, (void*)(st->m_aac_buffer + st->m_aac_bytes_consumed),
1326 st->m_aac_bytes_into_buffer*sizeof(unsigned char));
1327 }
1328
1329 if (!st->m_at_eof)
1330 {
1331 bread = fread((void*)(st->m_aac_buffer + st->m_aac_bytes_into_buffer),
1332 1, st->m_aac_bytes_consumed, st->aacfile);
1333
1334 if (bread != st->m_aac_bytes_consumed)
1335 st->m_at_eof = 1;
1336
1337 st->m_aac_bytes_into_buffer += bread;
1338 }
1339
1340 st->m_aac_bytes_consumed = 0;
1341
1342 if (st->m_aac_bytes_into_buffer > 3)
1343 {
1344 if (memcmp(st->m_aac_buffer, "TAG", 3) == 0)
1345 st->m_aac_bytes_into_buffer = 0;
1346 }
1347 if (st->m_aac_bytes_into_buffer > 11)
1348 {
1349 if (memcmp(st->m_aac_buffer, "LYRICSBEGIN", 11) == 0)
1350 st->m_aac_bytes_into_buffer = 0;
1351 }
1352 if (st->m_aac_bytes_into_buffer > 8)
1353 {
1354 if (memcmp(st->m_aac_buffer, "APETAGEX", 8) == 0)
1355 st->m_aac_bytes_into_buffer = 0;
1356 }
1357 }
1358
1359 return 1;
1360 }
1361
advance_buffer(state * st,int bytes)1362 void advance_buffer(state *st, int bytes)
1363 {
1364 st->m_file_offset += bytes;
1365 st->m_aac_bytes_consumed = bytes;
1366 st->m_aac_bytes_into_buffer -= bytes;
1367 }
1368
adts_parse(state * st,__int64 * bitrate,double * length)1369 int adts_parse(state *st, __int64 *bitrate, double *length)
1370 {
1371 static int sample_rates[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000};
1372 int frames, frame_length;
1373 int t_framelength = 0;
1374 int samplerate;
1375 double frames_per_sec, bytes_per_frame;
1376
1377 /* Read all frames to ensure correct time and bitrate */
1378 for (frames = 0; /* */; frames++)
1379 {
1380 fill_buffer(st);
1381
1382 if (st->m_aac_bytes_into_buffer > 7)
1383 {
1384 /* check syncword */
1385 if (!((st->m_aac_buffer[0] == 0xFF)&&((st->m_aac_buffer[1] & 0xF6) == 0xF0)))
1386 break;
1387
1388 st->m_tail->offset = st->m_file_offset;
1389 st->m_tail->next = (struct seek_list*)malloc(sizeof(struct seek_list));
1390 st->m_tail = st->m_tail->next;
1391 st->m_tail->next = NULL;
1392
1393 if (frames == 0)
1394 samplerate = sample_rates[(st->m_aac_buffer[2]&0x3c)>>2];
1395
1396 frame_length = ((((unsigned int)st->m_aac_buffer[3] & 0x3)) << 11)
1397 | (((unsigned int)st->m_aac_buffer[4]) << 3) | (st->m_aac_buffer[5] >> 5);
1398
1399 t_framelength += frame_length;
1400
1401 if (frame_length > st->m_aac_bytes_into_buffer)
1402 break;
1403
1404 advance_buffer(st, frame_length);
1405 } else {
1406 break;
1407 }
1408 }
1409
1410 frames_per_sec = (double)samplerate/1024.0;
1411 if (frames != 0)
1412 bytes_per_frame = (double)t_framelength/(double)(frames*1000);
1413 else
1414 bytes_per_frame = 0;
1415 *bitrate = (__int64)(8. * bytes_per_frame * frames_per_sec + 0.5);
1416 if (frames_per_sec != 0)
1417 *length = (double)frames/frames_per_sec;
1418 else
1419 *length = 1;
1420
1421 return 1;
1422 }
1423
skip_id3v2_tag()1424 int skip_id3v2_tag()
1425 {
1426 unsigned char buf[10];
1427 int bread, tagsize = 0;
1428
1429 bread = fread(buf, 1, 10, mp4state.aacfile);
1430 if (bread != 10) return -1;
1431
1432 if (!memcmp(buf, "ID3", 3))
1433 {
1434 /* high bit is not used */
1435 tagsize = (buf[6] << 21) | (buf[7] << 14) | (buf[8] << 7) | (buf[9] << 0);
1436
1437 tagsize += 10;
1438 fseek(mp4state.aacfile, tagsize, SEEK_SET);
1439 } else {
1440 fseek(mp4state.aacfile, 0, SEEK_SET);
1441 }
1442
1443 return tagsize;
1444 }
1445
GetMediaSupported(const char * medianame,MediaInfo * mediaInfo)1446 int GetMediaSupported(const char* medianame, MediaInfo *mediaInfo)
1447 {
1448 int tagsize = 0, init;
1449
1450 if (!medianame || !*medianame)
1451 return 0;
1452
1453 if (!stricmp(medianame + strlen(medianame) - 3,"MP4") || !stricmp(medianame + strlen(medianame) - 3,"M4A"))
1454 {
1455 if (mediaInfo)
1456 {
1457 mediaInfo->mediaType = DIGITAL_FILE_MEDIA;
1458 mediaInfo->op_canSeek = 1;
1459 }
1460 return 1;
1461 }
1462 else if (m_use_for_aac && !stricmp(medianame + strlen(medianame) - 3,"AAC"))
1463 {
1464 if (mediaInfo)
1465 {
1466 mediaInfo->mediaType = DIGITAL_FILE_MEDIA;
1467 mediaInfo->op_canSeek = 1;
1468
1469 memset(&mp4state, 0, sizeof(state));
1470 lstrcpy(mp4state.filename, medianame);
1471
1472 if (!(mp4state.aacfile = fopen(mp4state.filename, "rb")))
1473 {
1474 // error
1475 return 0;
1476 }
1477
1478 tagsize = skip_id3v2_tag();
1479 if (tagsize<0) return 0;
1480
1481 if (!(mp4state.m_aac_buffer = (unsigned char*)malloc(768*6)))
1482 {
1483 show_error(module.hMainWindow, "Memory allocation error.");
1484 return 0;
1485 }
1486
1487 for (init=0; init<2; init++)
1488 {
1489 memset(mp4state.m_aac_buffer, 0, 768*6);
1490 fread(mp4state.m_aac_buffer, 1, 768*6, mp4state.aacfile);
1491
1492 if (init==0)
1493 fseek(mp4state.aacfile, tagsize, SEEK_SET);
1494 }
1495
1496 if (memcmp(mp4state.m_aac_buffer, "ADIF", 4) == 0)
1497 mediaInfo->op_canSeek = (double)file_length(mp4state.aacfile) == -1 ? 0 : 1;
1498
1499 free(mp4state.m_aac_buffer);
1500
1501 fclose(mp4state.aacfile);
1502 }
1503 return 1;
1504 }
1505
1506 return 0;
1507 }
1508
1509 //-----------------------------------------------------------------------------
1510
Play(const char * medianame,int playfrom,int playto,int flags)1511 int Play(const char* medianame, int playfrom, int playto, int flags)
1512 {
1513 WAVEFORMATEX wf;
1514 //int maxlatency;
1515 int thread_id;
1516 int avg_bitrate, br, sr;
1517 unsigned char *buffer;
1518 int buffer_size;
1519 faacDecConfigurationPtr config;
1520
1521 #ifdef DEBUG_OUTPUT
1522 in_mp4_DebugOutput("play");
1523 #endif
1524
1525 if (stricmp(mp4state.filename, medianame) != 0)
1526 Stop(mp4state.filename, STOPFLAG_PLAYDONE);
1527
1528 if (mp4state.paused)
1529 {
1530 // Update the player controls to reflect the new unpaused state
1531 module.QCDCallbacks.toPlayer.OutputPause(0);
1532
1533 Pause(medianame, 0);
1534
1535 if (playfrom >= 0)
1536 mp4state.seek_needed = playfrom;
1537 }
1538 else if (PlayThreadAlive) // is playing
1539 {
1540 mp4state.seek_needed = playfrom;
1541 return 1;
1542 }
1543 else
1544 {
1545 memset(&mp4state, 0, sizeof(state));
1546
1547 lstrcpy(mp4state.filename, medianame);
1548
1549 if (!(mp4state.mp4file = MP4Read(mp4state.filename, 0)))
1550 {
1551 mp4state.filetype = 1;
1552 } else {
1553 MP4Close(mp4state.mp4file);
1554 mp4state.filetype = 0;
1555 }
1556
1557 if (mp4state.filetype)
1558 {
1559 int tagsize = 0, tmp = 0, init;
1560 int bread = 0;
1561 double length = 0.;
1562 __int64 bitrate = 128;
1563
1564 //module.is_seekable = 1;
1565
1566 if (!(mp4state.aacfile = fopen(mp4state.filename, "rb")))
1567 {
1568 // error
1569 return -1;
1570 }
1571
1572 tagsize = skip_id3v2_tag();
1573 if (tagsize<0) return 0;
1574
1575 if (!(mp4state.m_aac_buffer = (unsigned char*)malloc(768*6)))
1576 {
1577 show_error(module.hMainWindow, "Memory allocation error.");
1578 return -1;
1579 }
1580
1581 for (init=0; init<2; init++)
1582 {
1583 mp4state.hDecoder = faacDecOpen();
1584 if (!mp4state.hDecoder)
1585 {
1586 show_error(module.hMainWindow, "Unable to open decoder library.");
1587 return -1;
1588 }
1589
1590 config = faacDecGetCurrentConfiguration(mp4state.hDecoder);
1591 config->outputFormat = m_resolution + 1;
1592 config->downMatrix = m_downmix;
1593 faacDecSetConfiguration(mp4state.hDecoder, config);
1594
1595 memset(mp4state.m_aac_buffer, 0, 768*6);
1596 bread = fread(mp4state.m_aac_buffer, 1, 768*6, mp4state.aacfile);
1597 mp4state.m_aac_bytes_into_buffer = bread;
1598 mp4state.m_aac_bytes_consumed = 0;
1599 mp4state.m_file_offset = 0;
1600 mp4state.m_at_eof = (bread != 768*6) ? 1 : 0;
1601
1602 if (init==0)
1603 {
1604 faacDecFrameInfo frameInfo;
1605
1606 fill_buffer(&mp4state);
1607
1608 if ((mp4state.m_aac_bytes_consumed = faacDecInit(mp4state.hDecoder,
1609 mp4state.m_aac_buffer, mp4state.m_aac_bytes_into_buffer,
1610 &mp4state.samplerate, &mp4state.channels)) < 0)
1611 {
1612 show_error(module.hMainWindow, "Can't initialize decoder library.");
1613 return -1;
1614 }
1615 advance_buffer(&mp4state, mp4state.m_aac_bytes_consumed);
1616
1617 do {
1618 memset(&frameInfo, 0, sizeof(faacDecFrameInfo));
1619 fill_buffer(&mp4state);
1620 faacDecDecode(mp4state.hDecoder, &frameInfo, mp4state.m_aac_buffer, mp4state.m_aac_bytes_into_buffer);
1621 } while (!frameInfo.samples && !frameInfo.error);
1622
1623 if (frameInfo.error)
1624 {
1625 show_error(module.hMainWindow, faacDecGetErrorMessage(frameInfo.error));
1626 return -1;
1627 }
1628
1629 mp4state.channels = frameInfo.channels;
1630 mp4state.samplerate = frameInfo.samplerate;
1631 mp4state.framesize = (frameInfo.channels != 0) ? frameInfo.samples/frameInfo.channels : 0;
1632 /*
1633 sbr = frameInfo.sbr;
1634 profile = frameInfo.object_type;
1635 header_type = frameInfo.header_type;
1636 */
1637
1638 faacDecClose(mp4state.hDecoder);
1639 fseek(mp4state.aacfile, tagsize, SEEK_SET);
1640 }
1641 }
1642
1643 mp4state.m_head = (struct seek_list*)malloc(sizeof(struct seek_list));
1644 mp4state.m_tail = mp4state.m_head;
1645 mp4state.m_tail->next = NULL;
1646
1647 mp4state.m_header_type = 0;
1648 if ((mp4state.m_aac_buffer[0] == 0xFF) && ((mp4state.m_aac_buffer[1] & 0xF6) == 0xF0))
1649 {
1650 if (1) //(can_seek)
1651 {
1652 adts_parse(&mp4state, &bitrate, &length);
1653 fseek(mp4state.aacfile, tagsize, SEEK_SET);
1654
1655 bread = fread(mp4state.m_aac_buffer, 1, 768*6, mp4state.aacfile);
1656 if (bread != 768*6)
1657 mp4state.m_at_eof = 1;
1658 else
1659 mp4state.m_at_eof = 0;
1660 mp4state.m_aac_bytes_into_buffer = bread;
1661 mp4state.m_aac_bytes_consumed = 0;
1662
1663 mp4state.m_header_type = 1;
1664 }
1665 } else if (memcmp(mp4state.m_aac_buffer, "ADIF", 4) == 0) {
1666 int skip_size = (mp4state.m_aac_buffer[4] & 0x80) ? 9 : 0;
1667 bitrate = ((unsigned int)(mp4state.m_aac_buffer[4 + skip_size] & 0x0F)<<19) |
1668 ((unsigned int)mp4state.m_aac_buffer[5 + skip_size]<<11) |
1669 ((unsigned int)mp4state.m_aac_buffer[6 + skip_size]<<3) |
1670 ((unsigned int)mp4state.m_aac_buffer[7 + skip_size] & 0xE0);
1671
1672 length = (double)file_length(mp4state.aacfile);
1673 if (length == -1)
1674 {
1675 //module.is_seekable = 0;
1676 length = 0;
1677 } else {
1678 length = ((double)length*8.)/((double)bitrate) + 0.5;
1679 }
1680
1681 mp4state.m_header_type = 2;
1682 } else {
1683 length = (double)file_length(mp4state.aacfile);
1684 length = ((double)length*8.)/((double)bitrate*1000.) + 0.5;
1685
1686 //module.is_seekable = 1;
1687 }
1688
1689 mp4state.m_length = (int)(length*1000.);
1690
1691 fill_buffer(&mp4state);
1692 if ((mp4state.m_aac_bytes_consumed = faacDecInit(mp4state.hDecoder,
1693 mp4state.m_aac_buffer, mp4state.m_aac_bytes_into_buffer,
1694 &mp4state.samplerate, &mp4state.channels)) < 0)
1695 {
1696 show_error(module.hMainWindow, "Can't initialize decoder library.");
1697 return -1;
1698 }
1699 advance_buffer(&mp4state, mp4state.m_aac_bytes_consumed);
1700
1701 if (mp4state.m_header_type == 2)
1702 avg_bitrate = bitrate;
1703 else
1704 avg_bitrate = bitrate*1000;
1705 } else {
1706 mp4state.hDecoder = faacDecOpen();
1707 if (!mp4state.hDecoder)
1708 {
1709 show_error(module.hMainWindow, "Unable to open decoder library.");
1710 return -1;
1711 }
1712
1713 config = faacDecGetCurrentConfiguration(mp4state.hDecoder);
1714 config->outputFormat = m_resolution + 1;
1715 config->downMatrix = m_downmix;
1716 faacDecSetConfiguration(mp4state.hDecoder, config);
1717
1718 mp4state.mp4file = MP4Read(mp4state.filename, 0);
1719 if (!mp4state.mp4file)
1720 {
1721 show_error(module.hMainWindow, "Unable to open file.");
1722 faacDecClose(mp4state.hDecoder);
1723 return -1;
1724 }
1725
1726 if ((mp4state.mp4track = GetAACTrack(mp4state.mp4file)) < 0)
1727 {
1728 show_error(module.hMainWindow, "Unsupported Audio track type.");
1729 faacDecClose(mp4state.hDecoder);
1730 MP4Close(mp4state.mp4file);
1731 return -1;
1732 }
1733
1734 buffer = NULL;
1735 buffer_size = 0;
1736 MP4GetTrackESConfiguration(mp4state.mp4file, mp4state.mp4track,
1737 &buffer, &buffer_size);
1738 if (!buffer)
1739 {
1740 faacDecClose(mp4state.hDecoder);
1741 MP4Close(mp4state.mp4file);
1742 return -1;
1743 }
1744
1745 if(faacDecInit2(mp4state.hDecoder, buffer, buffer_size,
1746 &mp4state.samplerate, &mp4state.channels) < 0)
1747 {
1748 /* If some error initializing occured, skip the file */
1749 faacDecClose(mp4state.hDecoder);
1750 MP4Close(mp4state.mp4file);
1751 if (buffer) free (buffer);
1752 return -1;
1753 }
1754
1755 /* for gapless decoding */
1756 {
1757 mp4AudioSpecificConfig mp4ASC;
1758
1759 mp4state.timescale = MP4GetTrackTimeScale(mp4state.mp4file, mp4state.mp4track);
1760 mp4state.framesize = 1024;
1761 mp4state.useAacLength = 0;
1762
1763 if (buffer)
1764 {
1765 if (AudioSpecificConfig(buffer, buffer_size, &mp4ASC) >= 0)
1766 {
1767 if (mp4ASC.frameLengthFlag == 1) mp4state.framesize = 960;
1768 if (mp4ASC.sbr_present_flag == 1) mp4state.framesize *= 2;
1769 }
1770 }
1771 }
1772
1773 free(buffer);
1774
1775 avg_bitrate = MP4GetTrackIntegerProperty(mp4state.mp4file, mp4state.mp4track,
1776 "mdia.minf.stbl.stsd.mp4a.esds.decConfigDescr.avgBitrate");
1777
1778 mp4state.numSamples = MP4GetTrackNumberOfSamples(mp4state.mp4file, mp4state.mp4track);
1779 mp4state.sampleId = 1;
1780
1781 //module.is_seekable = 1;
1782 }
1783
1784 if (mp4state.channels == 0)
1785 {
1786 show_error(module.hMainWindow, "Number of channels not supported for playback.");
1787 faacDecClose(mp4state.hDecoder);
1788 if (mp4state.filetype)
1789 fclose(mp4state.aacfile);
1790 else
1791 MP4Close(mp4state.mp4file);
1792 return -1;
1793 }
1794
1795 if (m_downmix && (mp4state.channels == 5 || mp4state.channels == 6))
1796 mp4state.channels = 2;
1797
1798 wf.wFormatTag = WAVE_FORMAT_PCM;
1799 wf.cbSize = 0;
1800 wf.nChannels = mp4state.channels;
1801 wf.wBitsPerSample = res_table[m_resolution];
1802 wf.nSamplesPerSec = mp4state.samplerate;
1803 wf.nBlockAlign = wf.nChannels * wf.wBitsPerSample / 8;
1804 wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign;
1805 if (!module.QCDCallbacks.toPlayer.OutputOpen(mp4state.filename, &wf)) // error opening device
1806 {
1807 faacDecClose(mp4state.hDecoder);
1808 if (mp4state.filetype)
1809 fclose(mp4state.aacfile);
1810 else
1811 MP4Close(mp4state.mp4file);
1812 return -1;
1813 }
1814
1815 mp4state.paused = 0;
1816 mp4state.decode_pos_ms = 0;
1817 mp4state.seek_needed = -1;
1818
1819 //// initialize vis stuff
1820 //module.SAVSAInit(maxlatency, mp4state.samplerate);
1821 //module.VSASetInfo((int)mp4state.channels, mp4state.samplerate);
1822
1823 br = (int)floor(((float)avg_bitrate + 500.0)/1000.0 + 0.5);
1824 sr = (int)floor((float)mp4state.samplerate/1000.0 + 0.5);
1825 ai.struct_size = sizeof(AudioInfo);
1826 ai.frequency = sr*1000;
1827 ai.bitrate = br*1000;
1828 ai.mode = (mp4state.channels == 2) ? 0 : 3;
1829 ai.layer = 0;
1830 ai.level = 0;
1831 strcpy(ai.text, mp4state.filetype ? "AAC" : "MP4");
1832 module.QCDCallbacks.Service(opSetAudioInfo, &ai, sizeof(AudioInfo), 0);
1833
1834 //module.outMod->SetVolume(-666); // set the output plug-ins default volume
1835
1836 killPlayThread = 0;
1837
1838 if (mp4state.filetype)
1839 {
1840 if ((play_thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)AACPlayThread,
1841 (void *)&killPlayThread, 0, &thread_id)) == NULL)
1842 {
1843 show_error(module.hMainWindow, "Cannot create playback thread");
1844 faacDecClose(mp4state.hDecoder);
1845 fclose(mp4state.aacfile);
1846 return -1;
1847 }
1848 } else {
1849 if ((play_thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MP4PlayThread,
1850 (void *)&killPlayThread, 0, &thread_id)) == NULL)
1851 {
1852 show_error(module.hMainWindow, "Cannot create playback thread");
1853 faacDecClose(mp4state.hDecoder);
1854 MP4Close(mp4state.mp4file);
1855 return -1;
1856 }
1857 }
1858
1859 SetThreadAffinityMask(play_thread_handle, 1);
1860
1861 SetThreadPriority(play_thread_handle, priority_table[m_priority]);
1862 }
1863
1864 return 1;
1865 }
1866
1867 //-----------------------------------------------------------------------------
1868
Pause(const char * medianame,int flags)1869 int Pause(const char* medianame, int flags)
1870 {
1871 #ifdef DEBUG_OUTPUT
1872 in_mp4_DebugOutput("pause");
1873 #endif
1874
1875 mp4state.paused = flags;
1876
1877 if (module.QCDCallbacks.toPlayer.OutputPause(flags))
1878 return 1;
1879
1880 mp4state.paused = !flags;
1881 return 0;
1882 }
1883
1884 //void unpause()
1885 //{
1886 //#ifdef DEBUG_OUTPUT
1887 // in_mp4_DebugOutput("unpause");
1888 //#endif
1889 //
1890 // mp4state.paused = 0;
1891 // module.outMod->Pause(0);
1892 //}
1893 //
1894 //int ispaused()
1895 //{
1896 //#ifdef DEBUG_OUTPUT
1897 // in_mp4_DebugOutput("ispaused");
1898 //#endif
1899 //
1900 // return mp4state.paused;
1901 //}
1902
1903 //-----------------------------------------------------------------------------
1904
SetVolume(int levelleft,int levelright,int flags)1905 void SetVolume(int levelleft, int levelright, int flags)
1906 {
1907 #ifdef DEBUG_OUTPUT
1908 in_mp4_DebugOutput("setvolume");
1909 #endif
1910
1911 module.QCDCallbacks.toPlayer.OutputSetVol(levelleft, levelright, flags);
1912 }
1913
1914 //void setpan(int pan)
1915 //{
1916 //#ifdef DEBUG_OUTPUT
1917 // in_mp4_DebugOutput("setpan");
1918 //#endif
1919 //
1920 // module.outMod->SetPan(pan);
1921 //}
1922
1923 //-----------------------------------------------------------------------------
1924
Stop(const char * medianame,int flags)1925 int Stop(const char* medianame, int flags)
1926 {
1927 struct seek_list *target = mp4state.m_head;
1928
1929 #ifdef DEBUG_OUTPUT
1930 in_mp4_DebugOutput("stop");
1931 #endif
1932
1933 if (medianame && *medianame && stricmp(mp4state.filename, medianame) == 0)
1934 {
1935 module.QCDCallbacks.toPlayer.OutputStop(flags);
1936 killPlayThread = 1;
1937
1938 if (play_thread_handle != INVALID_HANDLE_VALUE)
1939 {
1940 if (WaitForSingleObject(play_thread_handle, INFINITE) == WAIT_TIMEOUT)
1941 TerminateThread(play_thread_handle,0);
1942 CloseHandle(play_thread_handle);
1943 play_thread_handle = INVALID_HANDLE_VALUE;
1944 }
1945
1946
1947 if (mp4state.m_aac_buffer)
1948 free(mp4state.m_aac_buffer);
1949
1950 while (target)
1951 {
1952 struct seek_list *tmp = target;
1953 target = target->next;
1954 if (tmp) free(tmp);
1955 }
1956 faacDecClose(mp4state.hDecoder);
1957 if (mp4state.filetype)
1958 fclose(mp4state.aacfile);
1959 else
1960 MP4Close(mp4state.mp4file);
1961
1962 //module.outMod->Close();
1963 //module.SAVSADeInit();
1964 mp4state.filename[0] = '\0';
1965 mp4state.paused = 0;
1966 }
1967
1968 return 1;
1969 }
1970
getsonglength(const char * fn)1971 int getsonglength(const char *fn)
1972 {
1973 long msDuration = 0;
1974
1975 if(!stricmp(fn + strlen(fn) - 3,"MP4") || !stricmp(fn + strlen(fn) - 3,"M4A"))
1976 {
1977 int track;
1978 MP4Duration length;
1979 MP4FileHandle file;
1980
1981 file = MP4Read(fn, 0);
1982 if (!file)
1983 return 0;
1984
1985 if ((track = GetAACTrack(file)) < 0)
1986 {
1987 MP4Close(file);
1988 return -1;
1989 }
1990
1991 length = MP4GetTrackDuration(file, track);
1992
1993 msDuration = MP4ConvertFromTrackDuration(file, track,
1994 length, MP4_MSECS_TIME_SCALE);
1995
1996 MP4Close(file);
1997
1998 return msDuration;
1999 } else {
2000 int tagsize = 0;
2001 int bread = 0;
2002 double length = 0.;
2003 __int64 bitrate = 128;
2004 struct seek_list *target;
2005 state len_state;
2006
2007 memset(&len_state, 0, sizeof(state));
2008
2009 if (!(len_state.aacfile = fopen(fn, "rb")))
2010 {
2011 // error
2012 return 0;
2013 }
2014
2015 len_state.m_at_eof = 0;
2016
2017 if (!(len_state.m_aac_buffer = (unsigned char*)malloc(768*6)))
2018 {
2019 //console::error("Memory allocation error.", "foo_mp4");
2020 return 0;
2021 }
2022 memset(len_state.m_aac_buffer, 0, 768*6);
2023
2024 bread = fread(len_state.m_aac_buffer, 1, 768*6, len_state.aacfile);
2025 len_state.m_aac_bytes_into_buffer = bread;
2026 len_state.m_aac_bytes_consumed = 0;
2027 len_state.m_file_offset = 0;
2028
2029 if (bread != 768*6)
2030 len_state.m_at_eof = 1;
2031
2032 if (!memcmp(len_state.m_aac_buffer, "ID3", 3))
2033 {
2034 /* high bit is not used */
2035 tagsize = (len_state.m_aac_buffer[6] << 21) | (len_state.m_aac_buffer[7] << 14) |
2036 (len_state.m_aac_buffer[8] << 7) | (len_state.m_aac_buffer[9] << 0);
2037
2038 tagsize += 10;
2039 advance_buffer(&len_state, tagsize);
2040 }
2041
2042 len_state.m_head = (struct seek_list*)malloc(sizeof(struct seek_list));
2043 len_state.m_tail = len_state.m_head;
2044 len_state.m_tail->next = NULL;
2045
2046 len_state.m_header_type = 0;
2047 if ((len_state.m_aac_buffer[0] == 0xFF) && ((len_state.m_aac_buffer[1] & 0xF6) == 0xF0))
2048 {
2049 if (1) //(m_reader->can_seek())
2050 {
2051 adts_parse(&len_state, &bitrate, &length);
2052 fseek(len_state.aacfile, tagsize, SEEK_SET);
2053
2054 bread = fread(len_state.m_aac_buffer, 1, 768*6, len_state.aacfile);
2055 if (bread != 768*6)
2056 len_state.m_at_eof = 1;
2057 else
2058 len_state.m_at_eof = 0;
2059 len_state.m_aac_bytes_into_buffer = bread;
2060 len_state.m_aac_bytes_consumed = 0;
2061
2062 len_state.m_header_type = 1;
2063 }
2064 } else if (memcmp(len_state.m_aac_buffer, "ADIF", 4) == 0) {
2065 int skip_size = (len_state.m_aac_buffer[4] & 0x80) ? 9 : 0;
2066 bitrate = ((unsigned int)(len_state.m_aac_buffer[4 + skip_size] & 0x0F)<<19) |
2067 ((unsigned int)len_state.m_aac_buffer[5 + skip_size]<<11) |
2068 ((unsigned int)len_state.m_aac_buffer[6 + skip_size]<<3) |
2069 ((unsigned int)len_state.m_aac_buffer[7 + skip_size] & 0xE0);
2070
2071 length = (double)file_length(len_state.aacfile);
2072 if (length == -1)
2073 length = 0;
2074 else
2075 length = ((double)length*8.)/((double)bitrate) + 0.5;
2076
2077 len_state.m_header_type = 2;
2078 } else {
2079 length = (double)file_length(len_state.aacfile);
2080 length = ((double)length*8.)/((double)bitrate*1000.) + 0.5;
2081
2082 len_state.m_header_type = 0;
2083 }
2084
2085 if (len_state.m_aac_buffer)
2086 free(len_state.m_aac_buffer);
2087
2088 target = len_state.m_head;
2089 while (target)
2090 {
2091 struct seek_list *tmp = target;
2092 target = target->next;
2093 if (tmp) free(tmp);
2094 }
2095
2096 fclose(len_state.aacfile);
2097
2098 return (int)(length*1000.);
2099 }
2100 }
2101
2102 //int getlength()
2103 //{
2104 // if (!mp4state.filetype)
2105 // {
2106 // int track;
2107 // long msDuration;
2108 // MP4Duration length;
2109 //
2110 // if ((track = GetAACTrack(mp4state.mp4file)) < 0)
2111 // {
2112 // return -1;
2113 // }
2114 //
2115 // length = MP4GetTrackDuration(mp4state.mp4file, track);
2116 //
2117 // msDuration = MP4ConvertFromTrackDuration(mp4state.mp4file, track,
2118 // length, MP4_MSECS_TIME_SCALE);
2119 //
2120 // return msDuration;
2121 // } else {
2122 // return mp4state.m_length;
2123 // }
2124 // return 0;
2125 //}
2126
2127 //-----------------------------------------------------------------------------
2128
GetCurrentPosition(const char * medianame,long * track,long * offset)2129 int GetCurrentPosition(const char* medianame, long *track, long *offset)
2130 {
2131 return module.QCDCallbacks.toPlayer.OutputGetCurrentPosition((UINT*)offset, 0);
2132 }
2133
2134 //void setoutputtime(int time_in_ms)
2135 //{
2136 //#ifdef DEBUG_OUTPUT
2137 // in_mp4_DebugOutput("setoutputtime");
2138 //#endif
2139 //
2140 // mp4state.seek_needed = time_in_ms;
2141 //}
2142
2143 //-----------------------------------------------------------------------------
2144
GetTrackExtents(const char * medianame,TrackExtents * ext,int flags)2145 int GetTrackExtents(const char* medianame, TrackExtents *ext, int flags)
2146 {
2147 int len;
2148 FILE *fh;
2149
2150 len = getsonglength((char *)medianame);
2151 fh = fopen(medianame, "rb");
2152 if (len <= 0 || !fh)
2153 return 0;
2154
2155 ext->track = 1;
2156 ext->start = 0;
2157 ext->end = len;
2158 ext->bytesize = file_length(fh);
2159 fclose(fh);
2160 ext->unitpersec = 1000;
2161
2162 return 1;
2163 }
2164
2165 //void eq_set(int on, char data[10], int preamp)
2166 //{
2167 //}
2168
remap_channels(unsigned char * data,unsigned int samples,unsigned int bps)2169 static void remap_channels(unsigned char *data, unsigned int samples, unsigned int bps)
2170 {
2171 unsigned int i;
2172
2173 switch (bps)
2174 {
2175 case 8:
2176 {
2177 unsigned char r1, r2, r3, r4, r5, r6;
2178 for (i = 0; i < samples; i += 6)
2179 {
2180 r1 = data[i];
2181 r2 = data[i+1];
2182 r3 = data[i+2];
2183 r4 = data[i+3];
2184 r5 = data[i+4];
2185 r6 = data[i+5];
2186 data[i] = r2;
2187 data[i+1] = r3;
2188 data[i+2] = r1;
2189 data[i+3] = r6;
2190 data[i+4] = r4;
2191 data[i+5] = r5;
2192 }
2193 }
2194 break;
2195
2196 case 16:
2197 default:
2198 {
2199 unsigned short r1, r2, r3, r4, r5, r6;
2200 unsigned short *sample_buffer = (unsigned short *)data;
2201 for (i = 0; i < samples; i += 6)
2202 {
2203 r1 = sample_buffer[i];
2204 r2 = sample_buffer[i+1];
2205 r3 = sample_buffer[i+2];
2206 r4 = sample_buffer[i+3];
2207 r5 = sample_buffer[i+4];
2208 r6 = sample_buffer[i+5];
2209 sample_buffer[i] = r2;
2210 sample_buffer[i+1] = r3;
2211 sample_buffer[i+2] = r1;
2212 sample_buffer[i+3] = r6;
2213 sample_buffer[i+4] = r4;
2214 sample_buffer[i+5] = r5;
2215 }
2216 }
2217 break;
2218
2219 case 24:
2220 case 32:
2221 {
2222 unsigned int r1, r2, r3, r4, r5, r6;
2223 unsigned int *sample_buffer = (unsigned int *)data;
2224 for (i = 0; i < samples; i += 6)
2225 {
2226 r1 = sample_buffer[i];
2227 r2 = sample_buffer[i+1];
2228 r3 = sample_buffer[i+2];
2229 r4 = sample_buffer[i+3];
2230 r5 = sample_buffer[i+4];
2231 r6 = sample_buffer[i+5];
2232 sample_buffer[i] = r2;
2233 sample_buffer[i+1] = r3;
2234 sample_buffer[i+2] = r1;
2235 sample_buffer[i+3] = r6;
2236 sample_buffer[i+4] = r4;
2237 sample_buffer[i+5] = r5;
2238 }
2239 }
2240 break;
2241 }
2242 }
2243
MP4PlayThread(void * b)2244 DWORD WINAPI MP4PlayThread(void *b)
2245 {
2246 int done = 0, updatepos = 0;
2247 int l;
2248 int seq_frames = 0;
2249 int seq_bytes = 0;
2250
2251 void *sample_buffer;
2252 unsigned char *buffer;
2253 int buffer_size;
2254 faacDecFrameInfo frameInfo;
2255
2256 WriteDataStruct wd;
2257
2258 #ifdef DEBUG_OUTPUT
2259 in_mp4_DebugOutput("MP4PlayThread");
2260 #endif
2261
2262 PlayThreadAlive = 1;
2263 mp4state.last_frame = 0;
2264 mp4state.initial = 1;
2265
2266 while (!*((int *)b))
2267 {
2268 /* seeking */
2269 if (mp4state.seek_needed != -1)
2270 {
2271 MP4Duration duration;
2272
2273 module.QCDCallbacks.toPlayer.OutputFlush((unsigned int)mp4state.decode_pos_ms);
2274 duration = MP4ConvertToTrackDuration(mp4state.mp4file,
2275 mp4state.mp4track, mp4state.seek_needed, MP4_MSECS_TIME_SCALE);
2276 mp4state.sampleId = MP4GetSampleIdFromTime(mp4state.mp4file,
2277 mp4state.mp4track, duration, 0);
2278
2279 mp4state.decode_pos_ms = mp4state.seek_needed;
2280 mp4state.seek_needed = -1;
2281 updatepos = 1;
2282 }
2283
2284 if (done)
2285 {
2286 if (module.QCDCallbacks.toPlayer.OutputDrain(0) && !(mp4state.seek_needed >= 0))
2287 {
2288 module.QCDCallbacks.toPlayer.OutputStop(STOPFLAG_PLAYDONE);
2289 module.QCDCallbacks.toPlayer.PlayDone(mp4state.filename);
2290 PlayThreadAlive = 0;
2291 }
2292 else if (mp4state.seek_needed >= 0)
2293 {
2294 done = 0;
2295 continue;
2296 }
2297 break;
2298 } else/* if (module.outMod->CanWrite() >= (2048*mp4state.channels*sizeof(short)))*/ {
2299
2300 if (mp4state.last_frame)
2301 {
2302 done = 1;
2303 } else {
2304 int rc;
2305
2306 /* for gapless decoding */
2307 char *buf;
2308 MP4Duration dur;
2309 unsigned int sample_count;
2310 unsigned int delay = 0;
2311
2312 /* get acces unit from MP4 file */
2313 buffer = NULL;
2314 buffer_size = 0;
2315
2316 rc = MP4ReadSample(mp4state.mp4file, mp4state.mp4track,
2317 mp4state.sampleId++, &buffer, &buffer_size,
2318 NULL, &dur, NULL, NULL);
2319 if (mp4state.sampleId-1 == 1) dur = 0;
2320 if (rc == 0 || buffer == NULL)
2321 {
2322 mp4state.last_frame = 1;
2323 sample_buffer = NULL;
2324 frameInfo.samples = 0;
2325 } else {
2326 sample_buffer = faacDecDecode(mp4state.hDecoder, &frameInfo,
2327 buffer, buffer_size);
2328 }
2329 if (frameInfo.error > 0)
2330 {
2331 show_error(module.hMainWindow, faacDecGetErrorMessage(frameInfo.error));
2332 mp4state.last_frame = 1;
2333 }
2334 if (mp4state.sampleId > mp4state.numSamples)
2335 mp4state.last_frame = 1;
2336
2337 if (buffer) free(buffer);
2338
2339 if (mp4state.useAacLength || (mp4state.timescale != mp4state.samplerate)) {
2340 sample_count = frameInfo.samples;
2341 } else {
2342 sample_count = (unsigned int)(dur * frameInfo.channels);
2343
2344 if (!mp4state.useAacLength && !mp4state.initial && (mp4state.sampleId < mp4state.numSamples/2) && (dur*frameInfo.channels != frameInfo.samples))
2345 {
2346 //fprintf(stderr, "MP4 seems to have incorrect frame duration, using values from AAC data.\n");
2347 mp4state.useAacLength = 1;
2348 sample_count = frameInfo.samples;
2349 }
2350 }
2351
2352 if (mp4state.initial && (sample_count < mp4state.framesize*mp4state.channels) && (frameInfo.samples > sample_count))
2353 {
2354 delay = frameInfo.samples - sample_count;
2355 }
2356
2357 if (!killPlayThread && (sample_count > 0))
2358 {
2359 buf = (char *)sample_buffer;
2360 mp4state.initial = 0;
2361
2362 switch (res_table[m_resolution])
2363 {
2364 case 8:
2365 buf += delay;
2366 break;
2367 case 16:
2368 default:
2369 buf += delay * 2;
2370 break;
2371 case 24:
2372 case 32:
2373 buf += delay * 4;
2374 break;
2375 case 64:
2376 buf += delay * 8;
2377 }
2378
2379 if (frameInfo.channels == 6 && frameInfo.num_lfe_channels)
2380 remap_channels(buf, sample_count, res_table[m_resolution]);
2381
2382 if (res_table[m_resolution] == 24)
2383 {
2384 /* convert libfaad output (3 bytes packed in 4) */
2385 char *temp_buffer = convert3in4to3in3(buf, sample_count);
2386 memcpy((void*)buf, (void*)temp_buffer, sample_count*3);
2387 free(temp_buffer);
2388 }
2389
2390 //module.SAAddPCMData(buf, (int)mp4state.channels, res_table[m_resolution],
2391 // mp4state.decode_pos_ms);
2392 //module.VSAAddPCMData(buf, (int)mp4state.channels, res_table[m_resolution],
2393 // mp4state.decode_pos_ms);
2394 mp4state.decode_pos_ms += (double)sample_count * 1000.0 /
2395 ((double)frameInfo.samplerate * (double)frameInfo.channels);
2396
2397 l = sample_count * res_table[m_resolution] / 8;
2398
2399 if (updatepos)
2400 {
2401 module.QCDCallbacks.toPlayer.PositionUpdate((unsigned int)mp4state.decode_pos_ms);
2402 updatepos = 0;
2403 }
2404
2405 wd.bytelen = l;
2406 wd.data = (short*)buf;
2407 wd.markerend = 0;
2408 wd.markerstart = (UINT)mp4state.decode_pos_ms;
2409 wd.bps = res_table[m_resolution];
2410 wd.nch = frameInfo.channels;
2411 wd.numsamples = sample_count/frameInfo.channels;
2412 wd.srate = frameInfo.samplerate;
2413
2414 if (!module.QCDCallbacks.toPlayer.OutputWrite(&wd))
2415 done = 1;
2416
2417 //if (module.dsp_isactive())
2418 //{
2419 // void *dsp_buffer = malloc(l*2);
2420 // memcpy(dsp_buffer, buf, l);
2421
2422 // l = module.dsp_dosamples((short*)dsp_buffer,
2423 // sample_count/frameInfo.channels,
2424 // res_table[m_resolution],
2425 // frameInfo.channels,
2426 // frameInfo.samplerate) *
2427 // (frameInfo.channels*(res_table[m_resolution]/8));
2428
2429 // module.outMod->Write(dsp_buffer, l);
2430 // if (dsp_buffer) free(dsp_buffer);
2431 //} else {
2432 // module.outMod->Write(buf, l);
2433 //}
2434
2435 /* VBR bitrate display */
2436 if (m_vbr_display)
2437 {
2438 seq_frames++;
2439 seq_bytes += frameInfo.bytesconsumed;
2440 if (seq_frames == (int)(floor((float)frameInfo.samplerate/(float)(sample_count/frameInfo.channels) + 0.5)))
2441 {
2442 ai.bitrate = (int)floor(((float)seq_bytes*8.)/1000. + 0.5) * 1000;
2443 ai.frequency = (int)floor(frameInfo.samplerate/1000. + 0.5) * 1000;
2444 ai.mode = (mp4state.channels == 2) ? 0 : 3;
2445 module.QCDCallbacks.Service(opSetAudioInfo, &ai, sizeof(AudioInfo), 0);
2446
2447 seq_frames = 0;
2448 seq_bytes = 0;
2449 }
2450 }
2451 }
2452 }
2453 }
2454
2455 Sleep(10);
2456
2457 // catch pause
2458 while (mp4state.paused && !killPlayThread)
2459 Sleep(50);
2460 }
2461
2462 PlayThreadAlive = 0;
2463
2464 return 0;
2465 }
2466
decode_aac_frame(state * st,faacDecFrameInfo * frameInfo)2467 void *decode_aac_frame(state *st, faacDecFrameInfo *frameInfo)
2468 {
2469 void *sample_buffer = NULL;
2470
2471 do
2472 {
2473 fill_buffer(st);
2474
2475 if (st->m_aac_bytes_into_buffer != 0)
2476 {
2477 sample_buffer = faacDecDecode(st->hDecoder, frameInfo,
2478 st->m_aac_buffer, st->m_aac_bytes_into_buffer);
2479
2480 if (st->m_header_type != 1)
2481 {
2482 if (st->last_offset < st->m_file_offset)
2483 {
2484 st->m_tail->offset = st->m_file_offset;
2485 st->m_tail->next = (struct seek_list*)malloc(sizeof(struct seek_list));
2486 st->m_tail = st->m_tail->next;
2487 st->m_tail->next = NULL;
2488 st->last_offset = st->m_file_offset;
2489 }
2490 }
2491
2492 advance_buffer(st, frameInfo->bytesconsumed);
2493 } else {
2494 break;
2495 }
2496
2497 } while (!frameInfo->samples && !frameInfo->error);
2498
2499 return sample_buffer;
2500 }
2501
aac_seek(state * st,double seconds)2502 int aac_seek(state *st, double seconds)
2503 {
2504 int i, frames;
2505 int bread;
2506 struct seek_list *target = st->m_head;
2507
2508 if (1 /*can_seek*/ && ((st->m_header_type == 1) || (seconds < st->cur_pos_sec)))
2509 {
2510 frames = (int)(seconds*((double)st->samplerate/(double)st->framesize) + 0.5);
2511
2512 for (i = 0; i < frames; i++)
2513 {
2514 if (target->next)
2515 target = target->next;
2516 else
2517 return 0;
2518 }
2519 if (target->offset == 0 && frames > 0)
2520 return 0;
2521 fseek(st->aacfile, target->offset, SEEK_SET);
2522 st->m_file_offset = target->offset;
2523
2524 bread = fread(st->m_aac_buffer, 1, 768*6, st->aacfile);
2525 if (bread != 768*6)
2526 st->m_at_eof = 1;
2527 else
2528 st->m_at_eof = 0;
2529 st->m_aac_bytes_into_buffer = bread;
2530 st->m_aac_bytes_consumed = 0;
2531 st->m_file_offset += bread;
2532
2533 faacDecPostSeekReset(st->hDecoder, -1);
2534
2535 return 1;
2536 } else {
2537 if (seconds > st->cur_pos_sec)
2538 {
2539 faacDecFrameInfo frameInfo;
2540
2541 frames = (int)((seconds - st->cur_pos_sec)*((double)st->samplerate/(double)st->framesize));
2542
2543 if (frames > 0)
2544 {
2545 for (i = 0; i < frames; i++)
2546 {
2547 memset(&frameInfo, 0, sizeof(faacDecFrameInfo));
2548 decode_aac_frame(st, &frameInfo);
2549
2550 if (frameInfo.error || (st->m_aac_bytes_into_buffer == 0))
2551 {
2552 if (frameInfo.error)
2553 {
2554 if (faacDecGetErrorMessage(frameInfo.error) != NULL)
2555 show_error(module.hMainWindow, faacDecGetErrorMessage(frameInfo.error));
2556 }
2557 return 0;
2558 }
2559 }
2560 }
2561
2562 faacDecPostSeekReset(st->hDecoder, -1);
2563 }
2564 return 1;
2565 }
2566 }
2567
AACPlayThread(void * b)2568 DWORD WINAPI AACPlayThread(void *b)
2569 {
2570 int done = 0, updatepos = 0;
2571 int l;
2572 int seq_frames = 0;
2573 int seq_bytes = 0;
2574
2575 WriteDataStruct wd;
2576
2577 #ifdef DEBUG_OUTPUT
2578 in_mp4_DebugOutput("AACPlayThread");
2579 #endif
2580
2581 PlayThreadAlive = 1;
2582 mp4state.last_frame = 0;
2583
2584 while (!*((int *)b))
2585 {
2586 /* seeking */
2587 if (mp4state.seek_needed != -1)
2588 {
2589 double ms;
2590
2591 ms = mp4state.seek_needed/1000;
2592 if (aac_seek(&mp4state, ms)!=0)
2593 {
2594 module.QCDCallbacks.toPlayer.OutputFlush((unsigned int)mp4state.decode_pos_ms);
2595 mp4state.cur_pos_sec = ms;
2596 mp4state.decode_pos_ms = mp4state.seek_needed;
2597 }
2598 mp4state.seek_needed = -1;
2599 updatepos = 1;
2600 }
2601
2602 if (done)
2603 {
2604 if (module.QCDCallbacks.toPlayer.OutputDrain(0) && !(mp4state.seek_needed >= 0))
2605 {
2606 module.QCDCallbacks.toPlayer.OutputStop(STOPFLAG_PLAYDONE);
2607 module.QCDCallbacks.toPlayer.PlayDone(mp4state.filename);
2608 PlayThreadAlive = 0;
2609 }
2610 else if (mp4state.seek_needed >= 0)
2611 {
2612 done = 0;
2613 continue;
2614 }
2615 break;
2616 } else/* if (module.outMod->CanWrite() >= (2048*mp4state.channels*sizeof(short)))*/ {
2617 faacDecFrameInfo frameInfo;
2618 void *sample_buffer;
2619
2620 memset(&frameInfo, 0, sizeof(faacDecFrameInfo));
2621
2622 sample_buffer = decode_aac_frame(&mp4state, &frameInfo);
2623
2624 if (frameInfo.error || (mp4state.m_aac_bytes_into_buffer == 0))
2625 {
2626 if (frameInfo.error)
2627 {
2628 if (faacDecGetErrorMessage(frameInfo.error) != NULL)
2629 show_error(module.hMainWindow, faacDecGetErrorMessage(frameInfo.error));
2630 }
2631 done = 1;
2632 }
2633
2634 if (!killPlayThread && (frameInfo.samples > 0))
2635 {
2636 if (frameInfo.channels == 6 && frameInfo.num_lfe_channels)
2637 remap_channels(sample_buffer, frameInfo.samples, res_table[m_resolution]);
2638
2639 if (res_table[m_resolution] == 24)
2640 {
2641 /* convert libfaad output (3 bytes packed in 4 bytes) */
2642 char *temp_buffer = convert3in4to3in3(sample_buffer, frameInfo.samples);
2643 memcpy((void*)sample_buffer, (void*)temp_buffer, frameInfo.samples*3);
2644 free(temp_buffer);
2645 }
2646
2647 //module.SAAddPCMData(sample_buffer, (int)mp4state.channels, res_table[m_resolution],
2648 // mp4state.decode_pos_ms);
2649 //module.VSAAddPCMData(sample_buffer, (int)mp4state.channels, res_table[m_resolution],
2650 // mp4state.decode_pos_ms);
2651 mp4state.decode_pos_ms += (double)frameInfo.samples * 1000.0 /
2652 ((double)frameInfo.samplerate* (double)frameInfo.channels);
2653
2654 l = frameInfo.samples * res_table[m_resolution] / 8;
2655
2656 if (updatepos)
2657 {
2658 module.QCDCallbacks.toPlayer.PositionUpdate((unsigned int)mp4state.decode_pos_ms);
2659 updatepos = 0;
2660 }
2661
2662 wd.bytelen = l;
2663 wd.data = (short*)sample_buffer;
2664 wd.markerend = 0;
2665 wd.markerstart = (UINT)mp4state.decode_pos_ms;
2666 wd.bps = res_table[m_resolution];
2667 wd.nch = frameInfo.channels;
2668 wd.numsamples = frameInfo.samples/frameInfo.channels;
2669 wd.srate = frameInfo.samplerate;
2670
2671 if (!module.QCDCallbacks.toPlayer.OutputWrite(&wd))
2672 done = 1;
2673
2674 //if (module.dsp_isactive())
2675 //{
2676 // void *dsp_buffer = malloc(l*2);
2677 // memcpy(dsp_buffer, sample_buffer, l);
2678
2679 // l = module.dsp_dosamples((short*)dsp_buffer,
2680 // frameInfo.samples/frameInfo.channels,
2681 // res_table[m_resolution],
2682 // frameInfo.channels,
2683 // frameInfo.samplerate) *
2684 // (frameInfo.channels*(res_table[m_resolution]/8));
2685
2686 // module.outMod->Write(dsp_buffer, l);
2687 // if (dsp_buffer) free(dsp_buffer);
2688 //} else {
2689 // module.outMod->Write(sample_buffer, l);
2690 //}
2691
2692 /* VBR bitrate display */
2693 if (m_vbr_display)
2694 {
2695 seq_frames++;
2696 seq_bytes += frameInfo.bytesconsumed;
2697 if (seq_frames == (int)(floor((float)frameInfo.samplerate/(float)(frameInfo.samples/frameInfo.channels) + 0.5)))
2698 {
2699 ai.bitrate = (int)floor(((float)seq_bytes*8.)/1000. + 0.5) * 1000;
2700 ai.frequency = (int)floor(frameInfo.samplerate/1000. + 0.5) * 1000;
2701 ai.mode = (mp4state.channels == 2) ? 0 : 3;
2702 module.QCDCallbacks.Service(opSetAudioInfo, &ai, sizeof(AudioInfo), 0);
2703
2704 seq_frames = 0;
2705 seq_bytes = 0;
2706 }
2707 }
2708 }
2709
2710 if (frameInfo.channels > 0 && mp4state.samplerate > 0)
2711 mp4state.cur_pos_sec += ((double)(frameInfo.samples/frameInfo.channels))/(double)mp4state.samplerate;
2712 }
2713
2714 Sleep(10);
2715
2716 // catch pause
2717 while (mp4state.paused && !killPlayThread)
2718 Sleep(50);
2719 }
2720
2721 PlayThreadAlive = 0;
2722
2723 return 0;
2724 }
2725
2726 //-----------------------------------------------------------------------------
2727
DllMain(HINSTANCE hInst,DWORD fdwReason,LPVOID pRes)2728 int WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, LPVOID pRes)
2729 {
2730 if (fdwReason == DLL_PROCESS_ATTACH)
2731 {
2732 module.hDllInstance = hInst;
2733 }
2734 return 1;
2735 }
2736
2737 //-----------------------------------------------------------------------------
2738
INPUTDLL_ENTRY_POINT(QCDModInitIn * ModInit,QCDModInfo * ModInfo)2739 PLUGIN_API QCDModInitIn* INPUTDLL_ENTRY_POINT(QCDModInitIn *ModInit, QCDModInfo *ModInfo)
2740 {
2741 module.QCDCallbacks.size = sizeof(QCDModInitIn);
2742 module.QCDCallbacks.version = PLUGIN_API_VERSION;
2743 module.QCDCallbacks.toModule.Initialize = Initialize;
2744 module.QCDCallbacks.toModule.ShutDown = ShutDown;
2745 module.QCDCallbacks.toModule.GetTrackExtents = GetTrackExtents;
2746 module.QCDCallbacks.toModule.GetMediaSupported = GetMediaSupported;
2747 module.QCDCallbacks.toModule.Play = Play;
2748 module.QCDCallbacks.toModule.Pause = Pause;
2749 module.QCDCallbacks.toModule.Stop = Stop;
2750 module.QCDCallbacks.toModule.About = About;
2751 module.QCDCallbacks.toModule.Configure = Configure;
2752 module.QCDCallbacks.toModule.SetEQ = NULL;
2753 module.QCDCallbacks.toModule.SetVolume = SetVolume;
2754
2755 return &module.QCDCallbacks;
2756 }
2757
2758 ///* new Media Library interface */
2759 //
2760 //int mp4_get_metadata(MP4FileHandle file, const char *item, char *dest, int dlen)
2761 //{
2762 // char *pVal = NULL, dummy1[4096];
2763 // short dummy = 0, dummy2 = 0;
2764 //
2765 // if (dlen < 1) return 0;
2766 //
2767 // if (!stricmp(item, "track") || !stricmp(item, "tracknumber"))
2768 // {
2769 // if (MP4GetMetadataTrack(file, &dummy, &dummy2))
2770 // {
2771 // wsprintf(dummy1, "%d", (int)dummy);
2772 // strncpy(dest, dummy1, dlen-1);
2773 // dest[dlen-1] = '\0';
2774 // return 1;
2775 // }
2776 // }
2777 // else if (!stricmp(item, "disc") || !stricmp(item, "disknumber"))
2778 // {
2779 // if (MP4GetMetadataDisk(file, &dummy, &dummy2))
2780 // {
2781 // wsprintf(dummy1, "%d", (int)dummy);
2782 // strncpy(dest, dummy1, dlen-1);
2783 // dest[dlen-1] = '\0';
2784 // return 1;
2785 // }
2786 // }
2787 // else if (!stricmp(item, "compilation"))
2788 // {
2789 // u_int8_t cpil = 0;
2790 // if (MP4GetMetadataCompilation(file, &cpil))
2791 // {
2792 // wsprintf(dummy1, "%d", (int)cpil);
2793 // strncpy(dest, dummy1, dlen-1);
2794 // dest[dlen-1] = '\0';
2795 // return 1;
2796 // }
2797 // }
2798 // else if (!stricmp(item, "tempo"))
2799 // {
2800 // u_int16_t tempo = 0;
2801 // if (MP4GetMetadataTempo(file, &tempo))
2802 // {
2803 // wsprintf(dummy1, "%d", (int)tempo);
2804 // strncpy(dest, dummy1, dlen-1);
2805 // dest[dlen-1] = '\0';
2806 // return 1;
2807 // }
2808 // }
2809 // else if (!stricmp(item, "artist"))
2810 // {
2811 // if (MP4GetMetadataArtist(file, &pVal))
2812 // {
2813 // strncpy(dest, pVal, dlen-1);
2814 // dest[dlen-1] = '\0';
2815 // return 1;
2816 // }
2817 // }
2818 // else if (!stricmp(item, "writer"))
2819 // {
2820 // if (MP4GetMetadataWriter(file, &pVal))
2821 // {
2822 // strncpy(dest, pVal, dlen-1);
2823 // dest[dlen-1] = '\0';
2824 // return 1;
2825 // }
2826 // }
2827 // else if (!stricmp(item, "title"))
2828 // {
2829 // if (MP4GetMetadataName(file, &pVal))
2830 // {
2831 // strncpy(dest, pVal, dlen-1);
2832 // dest[dlen-1] = '\0';
2833 // return 1;
2834 // }
2835 // }
2836 // else if (!stricmp(item, "album"))
2837 // {
2838 // if (MP4GetMetadataAlbum(file, &pVal))
2839 // {
2840 // strncpy(dest, pVal, dlen-1);
2841 // dest[dlen-1] = '\0';
2842 // return 1;
2843 // }
2844 // }
2845 // else if (!stricmp(item, "date") || !stricmp(item, "year"))
2846 // {
2847 // if (MP4GetMetadataYear(file, &pVal))
2848 // {
2849 // strncpy(dest, pVal, dlen-1);
2850 // dest[dlen-1] = '\0';
2851 // return 1;
2852 // }
2853 // }
2854 // else if (!stricmp(item, "comment"))
2855 // {
2856 // if (MP4GetMetadataComment(file, &pVal))
2857 // {
2858 // strncpy(dest, pVal, dlen-1);
2859 // dest[dlen-1] = '\0';
2860 // return 1;
2861 // }
2862 // }
2863 // else if (!stricmp(item, "genre"))
2864 // {
2865 // if (MP4GetMetadataGenre(file, &pVal))
2866 // {
2867 // strncpy(dest, pVal, dlen-1);
2868 // dest[dlen-1] = '\0';
2869 // return 1;
2870 // }
2871 // }
2872 // else if (!stricmp(item, "tool"))
2873 // {
2874 // if (MP4GetMetadataTool(file, &pVal))
2875 // {
2876 // strncpy(dest, pVal, dlen-1);
2877 // dest[dlen-1] = '\0';
2878 // return 1;
2879 // }
2880 // }
2881 // else
2882 // {
2883 // u_int32_t valueSize = 0;
2884 // u_int8_t *pValue = NULL;
2885 //
2886 // if (MP4GetMetadataFreeForm(file, (char *)item, &pValue, &valueSize))
2887 // {
2888 // unsigned int len = (valueSize < (unsigned int)(dlen-1)) ? valueSize : (unsigned int)(dlen-1);
2889 // memcpy(dest, pValue, len);
2890 // dest[len] = '\0';
2891 // return 1;
2892 // }
2893 // }
2894 //
2895 // return 0;
2896 //}
2897 //
2898 //__declspec(dllexport) int winampGetExtendedFileInfo(const char *fn, const char *data, char *dest, int destlen)
2899 //{
2900 // if (!fn || (fn && !*fn) || !destlen) return 0;
2901 //
2902 // dest[0] = '\0';
2903 //
2904 // if (!stricmp(data, "length"))
2905 // {
2906 // char temp[32];
2907 // int len = getsonglength(fn);
2908 // itoa(len, temp, 10);
2909 // strncpy(dest, temp, destlen-1);
2910 // dest[destlen-1] = '\0';
2911 // }
2912 // else
2913 // {
2914 // char temp[2048], temp2[2048];
2915 // MP4FileHandle file = MP4Read(fn, 0);
2916 // if (file == MP4_INVALID_FILE_HANDLE) return 0;
2917 //
2918 // if (mp4_get_metadata(file, data, temp, sizeof(temp)))
2919 // {
2920 // int len = ConvertUTF8ToANSI(temp, temp2);
2921 // if (len > destlen-1) len = destlen-1;
2922 // memcpy(dest, temp2, len);
2923 // dest[len] = '\0';
2924 // }
2925 //
2926 // MP4Close(file);
2927 // }
2928 //
2929 // return 1;
2930 //}
2931 //
2932 //static struct medialib_tags mltags = {0, 0};
2933 //static BOOL medialib_init = FALSE;
2934 //static char medialib_lastfn[2048] = "";
2935 //
2936 //__declspec(dllexport) int winampSetExtendedFileInfo(const char *fn, const char *data, char *val)
2937 //{
2938 // int len, ret = 0;
2939 // char *temp;
2940 //
2941 // if (!medialib_init || (medialib_init && stricmp(fn, medialib_lastfn))) {
2942 // MP4FileHandle file;
2943 // strcpy(medialib_lastfn, fn);
2944 //
2945 // if (medialib_init) tag_delete(&mltags);
2946 //
2947 // file = MP4Read(fn, 0);
2948 // if (file == MP4_INVALID_FILE_HANDLE) return 0;
2949 // ReadMP4Tag(file, &mltags);
2950 // MP4Close(file);
2951 // medialib_init = TRUE;
2952 // }
2953 //
2954 // len = strlen(val);
2955 // temp = (char *)malloc((len+1)*4);
2956 // if (!temp) return 0;
2957 //
2958 // if (ConvertANSIToUTF8(val, temp))
2959 // {
2960 // ret = 1;
2961 // tag_set_field(&mltags, data, temp);
2962 // }
2963 //
2964 // free(temp);
2965 //
2966 // return ret;
2967 //}
2968 //
2969 //__declspec(dllexport) int winampWriteExtendedFileInfo()
2970 //{
2971 // if (medialib_init)
2972 // {
2973 // MP4FileHandle file = MP4Modify(medialib_lastfn, 0, 0);
2974 // if (file == MP4_INVALID_FILE_HANDLE) return 0;
2975 //
2976 // MP4MetadataDelete(file);
2977 // MP4Close(file);
2978 //
2979 // file = MP4Modify(medialib_lastfn, 0, 0);
2980 // if (file == MP4_INVALID_FILE_HANDLE) return 0;
2981 //
2982 // WriteMP4Tag(file, &mltags);
2983 //
2984 // MP4Close(file);
2985 //
2986 // return 1;
2987 // }
2988 // else
2989 // {
2990 // return 0;
2991 // }
2992 //}
2993