ref: 3192dd937a71f737af84273806d91b306526cece
parent: c6050d407a25bfa81573cff01bdadb65ef6cfb5f
author: menno <menno>
date: Wed Aug 14 13:55:49 EDT 2002
New info box for mp4 plugin mp4 plugin now supports seeking in aac files and info for aac files (seems a bit buggy)
--- /dev/null
+++ b/plugins/in_mp4/aacinfo.c
@@ -1,0 +1,242 @@
+/*
+** FAAD - Freeware Advanced Audio Decoder
+** Copyright (C) 2002 M. Bakker
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+** $Id: aacinfo.c,v 1.1 2002/08/14 17:55:49 menno Exp $
+**/
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+#include <malloc.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "aacinfo.h"
+#include "utils.h"
+
+#define ADIF_MAX_SIZE 30 /* Should be enough */
+#define ADTS_MAX_SIZE 10 /* Should be enough */
+
+static int sample_rates[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000};
+
+static int read_ADIF_header(FILE *file, faadAACInfo *info)
+{
+ int bitstream;
+ unsigned char buffer[ADIF_MAX_SIZE];
+ int skip_size = 0;
+ int sf_idx;
+
+ /* Get ADIF header data */
+ info->headertype = 1;
+
+ if (fread(buffer, 1, ADIF_MAX_SIZE, file) != ADIF_MAX_SIZE)
+ return -1;
+
+ /* copyright string */
+ if(buffer[0] & 0x80)
+ skip_size += 9; /* skip 9 bytes */
+
+ bitstream = buffer[0 + skip_size] & 0x10;
+ info->bitrate = ((unsigned int)(buffer[0 + skip_size] & 0x0F)<<19)|
+ ((unsigned int)buffer[1 + skip_size]<<11)|
+ ((unsigned int)buffer[2 + skip_size]<<3)|
+ ((unsigned int)buffer[3 + skip_size] & 0xE0);
+
+ if (bitstream == 0)
+ {
+ info->object_type = ((buffer[6 + skip_size]&0x01)<<1)|((buffer[7 + skip_size]&0x80)>>7);
+ sf_idx = (buffer[7 + skip_size]&0x78)>>3;
+ } else {
+ info->object_type = (buffer[4 + skip_size] & 0x18)>>3;
+ sf_idx = ((buffer[4 + skip_size] & 0x07)<<1)|((buffer[5 + skip_size] & 0x80)>>7);
+ }
+ info->sampling_rate = sample_rates[sf_idx];
+
+ return 0;
+}
+
+static int read_ADTS_header(FILE *file, faadAACInfo *info, unsigned long **seek_table,
+ int *seek_table_len, int use_seek_table)
+{
+ /* Get ADTS header data */
+ unsigned char buffer[ADTS_MAX_SIZE];
+ int frames, framesinsec=0, t_framelength = 0, frame_length, sr_idx = 0, ID;
+ int second = 0, pos;
+ float frames_per_sec = 0;
+ unsigned long bytes;
+ unsigned long *tmp_seek_table = NULL;
+
+ info->headertype = 2;
+
+ /* Read all frames to ensure correct time and bitrate */
+ for (frames = 0; /* */; frames++, framesinsec++)
+ {
+ bytes = fread(buffer, 1, ADTS_MAX_SIZE, file);
+
+ if (bytes != ADTS_MAX_SIZE)
+ break;
+
+ /* check syncword */
+ if (!((buffer[0] == 0xFF)&&((buffer[1] & 0xF6) == 0xF0)))
+ break;
+
+ if (!frames)
+ {
+ /* fixed ADTS header is the same for every frame, so we read it only once */
+ /* Syncword found, proceed to read in the fixed ADTS header */
+ ID = buffer[1] & 0x08;
+ info->object_type = (buffer[2]&0xC0)>>6;
+ sr_idx = (buffer[2]&0x3C)>>2;
+ info->channels = ((buffer[2]&0x01)<<2)|((buffer[3]&0xC0)>>6);
+
+ frames_per_sec = sample_rates[sr_idx] / 1024.f;
+ }
+
+ /* ...and the variable ADTS header */
+ if (ID == 0)
+ {
+ info->version = 4;
+ frame_length = (((unsigned int)buffer[4]) << 5) |
+ ((unsigned int)buffer[5] >> 3);
+ } else { /* MPEG-2 */
+ info->version = 2;
+ frame_length = ((((unsigned int)buffer[3] & 0x3)) << 11)
+ | (((unsigned int)buffer[4]) << 3) | (buffer[5] >> 5);
+ }
+
+ t_framelength += frame_length;
+
+ if (framesinsec > 43)
+ framesinsec = 0;
+
+ pos = ftell(file) - ADTS_MAX_SIZE;
+
+ if (framesinsec == 0 && use_seek_table)
+ {
+ tmp_seek_table = (unsigned long*)realloc(tmp_seek_table, (second+1) * sizeof(unsigned long));
+ tmp_seek_table[second] = pos;
+ }
+ if (framesinsec == 0)
+ second++;
+
+ fseek(file, frame_length - ADTS_MAX_SIZE, SEEK_CUR);
+ }
+
+ if(seek_table_len)
+ {
+ *seek_table_len = second;
+ *seek_table = tmp_seek_table;
+ }
+
+ if (frames > 0)
+ {
+ info->sampling_rate = sample_rates[sr_idx];
+ info->bitrate = (int)(((t_framelength / frames) * (info->sampling_rate/1024.0)) +0.5)*8;
+ info->length = (int)((float)(frames/frames_per_sec))*1000;
+ } else {
+ info->sampling_rate = 4;
+ info->bitrate = 128000;
+ info->length = 0;
+ info->channels = 0;
+ }
+
+ return 0;
+}
+
+int get_AAC_format(char *filename, faadAACInfo *info,
+ unsigned long **seek_table, int *seek_table_len,
+ int use_seek_table)
+{
+ unsigned long tagsize;
+ FILE *file;
+ char buffer[10];
+ unsigned long file_len;
+ unsigned char adxx_id[5];
+ unsigned long tmp;
+
+ memset(info, 0, sizeof(faadAACInfo));
+
+ file = fopen(filename, "rb");
+
+ if(file == NULL)
+ return -1;
+
+ fseek(file, 0, SEEK_END);
+ file_len = ftell(file);
+ fseek(file, 0, SEEK_SET);
+
+ /* Skip the tag, if it's there */
+ tmp = fread(buffer, 10, 1, file);
+
+ if (StringComp(buffer, "ID3", 3) == 0)
+ {
+ /* high bit is not used */
+ tagsize = (buffer[6] << 21) | (buffer[7] << 14) |
+ (buffer[8] << 7) | (buffer[9] << 0);
+
+ fseek(file, tagsize, SEEK_CUR);
+ tagsize += 10;
+ } else {
+ tagsize = 0;
+ fseek(file, 0, SEEK_SET);
+ }
+
+ if (file_len)
+ file_len -= tagsize;
+
+ tmp = fread(adxx_id, 2, 1, file);
+ adxx_id[5-1] = 0;
+ info->length = 0;
+
+ /* Determine the header type of the file, check the first two bytes */
+ if (StringComp(adxx_id, "AD", 2) == 0)
+ {
+ /* We think its an ADIF header, but check the rest just to make sure */
+ tmp = fread(adxx_id + 2, 2, 1, file);
+
+ if (StringComp(adxx_id, "ADIF", 4) == 0)
+ {
+ read_ADIF_header(file, info);
+
+ info->length = (int)((float)file_len*8000.0/((float)info->bitrate));
+ }
+ } else {
+ /* No ADIF, check for ADTS header */
+ if ((adxx_id[0] == 0xFF)&&((adxx_id[1] & 0xF6) == 0xF0))
+ {
+ /* ADTS header located */
+ fseek(file, tagsize, SEEK_SET);
+
+ read_ADTS_header(file, info, seek_table, seek_table_len,
+ use_seek_table);
+ } else {
+ /* Unknown/headerless AAC file, assume format: */
+ info->version = 2;
+ info->bitrate = 128000;
+ info->sampling_rate = 44100;
+ info->channels = 2;
+ info->headertype = 0;
+ info->object_type = 1;
+ }
+ }
+
+ fclose(file);
+
+ return 0;
+}
+
--- /dev/null
+++ b/plugins/in_mp4/aacinfo.h
@@ -1,0 +1,44 @@
+/*
+** FAAD - Freeware Advanced Audio Decoder
+** Copyright (C) 2002 M. Bakker
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+** $Id: aacinfo.h,v 1.1 2002/08/14 17:55:49 menno Exp $
+**/
+
+#ifndef AACINFO_INCLUDED
+#define AACINFO_INCLUDED
+
+typedef struct {
+ int version;
+ int channels;
+ int sampling_rate;
+ int bitrate;
+ int length;
+ int object_type;
+ int headertype;
+} faadAACInfo;
+
+int get_AAC_format(char *filename, faadAACInfo *info,
+ unsigned long **seek_table, int *seek_table_len,
+ int use_seek_table);
+
+static int read_ADIF_header(FILE *file, faadAACInfo *info);
+static int read_ADTS_header(FILE *file, faadAACInfo *info,
+ unsigned long **seek_table, int *seek_table_len,
+ int use_seek_table);
+
+#endif
--- a/plugins/in_mp4/in_mp4.c
+++ b/plugins/in_mp4/in_mp4.c
@@ -16,7 +16,7 @@
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
-** $Id: in_mp4.c,v 1.13 2002/08/09 21:48:12 menno Exp $
+** $Id: in_mp4.c,v 1.14 2002/08/14 17:55:20 menno Exp $
**/
#define WIN32_LEAN_AND_MEAN
@@ -30,6 +30,7 @@
#include "in2.h"
#include "utils.h"
#include "config.h"
+#include "aacinfo.h"
static long priority_table[] = {
0,
@@ -42,12 +43,16 @@
static int res_id_table[] = {
IDC_16BITS,
IDC_24BITS,
- IDC_32BITS
+ IDC_32BITS,
+ 0,
+ IDC_16BITS_DITHERED
};
static int res_table[] = {
16,
24,
- 32
+ 32,
+ 0,
+ 16
};
static char info_fn[_MAX_PATH];
@@ -65,6 +70,7 @@
int seek_needed; // if != -1, it is the point that the decode thread should seek to, in ms.
char filename[_MAX_PATH];
int filetype; /* 0: MP4; 1: AAC */
+ int last_frame;
/* MP4 stuff */
MP4FileHandle mp4file;
@@ -79,7 +85,10 @@
long bytes_into_buffer;
long bytes_consumed;
unsigned char *buffer;
- long lengthMs;
+ long seconds;
+ unsigned long *seek_table;
+ int seek_table_len;
+ faadAACInfo aacInfo;
} state;
static state mp4state;
@@ -157,204 +166,87 @@
BOOL CALLBACK mp4_info_dialog_proc(HWND hwndDlg, UINT message,
WPARAM wParam, LPARAM lParam)
{
- int i, width, height, numFrames;
- unsigned char ch, sf, dummy8;
- float fps;
MP4FileHandle file;
- int track;
- char info[256];
+ int tracks, i;
- static const char* mpeg4AudioNames[] = {
- "MPEG-4 Null (Raw PCM)",
- "MPEG-4 AAC Main",
- "MPEG-4 AAC LC",
- "MPEG-4 AAC SSR",
- "MPEG-4 AAC LTP",
- "Reserved",
- "MPEG-4 AAC Scalable",
- "MPEG-4 TwinVQ",
- "MPEG-4 CELP",
- "MPEG-4 HVXC",
- "Reserved",
- "Reserved",
- "MPEG-4 TTSI",
- "MPEG-4 Main synthetic",
- "MPEG-4 Wavetable synthesis",
- "MPEG-4 General MIDI",
- "MPEG-4 Algorithmic Synthesis and Audio FX",
- /* defined in MPEG-4 version 2 */
- "MPEG-4 ER AAC LC",
- "Reserved",
- "MPEG-4 ER AAC LTP",
- "MPEG-4 ER AAC Scalable",
- "MPEG-4 ER TwinVQ",
- "MPEG-4 ER BSAC",
- "MPEG-4 ER AAC LD",
- "MPEG-4 ER CELP",
- "MPEG-4 ER HVXC",
- "MPEG-4 ER HILN",
- "MPEG-4 ER Parametric",
- "Reserved",
- "Reserved",
- "Reserved",
- "Reserved"
- };
- static int numMpeg4AudioTypes =
- sizeof(mpeg4AudioNames)/sizeof(char*);
-
- static const char* mpeg4VideoNames[] = {
- "MPEG-4 Simple @ L3",
- "MPEG-4 Simple @ L2",
- "MPEG-4 Simple @ L1",
- "MPEG-4 Simple Scalable @ L2",
- "MPEG-4 Simple Scalable @ L1",
- "MPEG-4 Core @ L2",
- "MPEG-4 Core @ L1",
- "MPEG-4 Main @ L4",
- "MPEG-4 Main @ L3",
- "MPEG-4 Main @ L2",
- "MPEG-4 Main @ L1",
- "MPEG-4 N-Bit @ L2",
- "MPEG-4 Hybrid @ L2",
- "MPEG-4 Hybrid @ L1",
- "MPEG-4 Hybrid @ L1"
- };
- static int numMpeg4VideoTypes =
- sizeof(mpeg4VideoNames) / sizeof(char*);
-
- static int mpegVideoTypes[] = {
- MP4_MPEG2_SIMPLE_VIDEO_TYPE, // 0x60
- MP4_MPEG2_MAIN_VIDEO_TYPE, // 0x61
- MP4_MPEG2_SNR_VIDEO_TYPE, // 0x62
- MP4_MPEG2_SPATIAL_VIDEO_TYPE, // 0x63
- MP4_MPEG2_HIGH_VIDEO_TYPE, // 0x64
- MP4_MPEG2_442_VIDEO_TYPE, // 0x65
- MP4_MPEG1_VIDEO_TYPE, // 0x6A
- MP4_JPEG_VIDEO_TYPE // 0x6C
- };
- static const char* mpegVideoNames[] = {
- "MPEG-2 Simple",
- "MPEG-2 Main",
- "MPEG-2 SNR",
- "MPEG-2 Spatial",
- "MPEG-2 High",
- "MPEG-2 4:2:2",
- "MPEG-1",
- "JPEG"
- };
- static int numMpegVideoTypes =
- sizeof(mpegVideoTypes) / sizeof(u_int8_t);
-
- unsigned long msDuration;
- MP4Duration trackDuration;
- unsigned int timeScale, avgBitRate;
- unsigned char type;
- const char* typeName;
-
switch (message) {
case WM_INITDIALOG:
file = MP4Read(info_fn, 0);
+
if (!file)
return FALSE;
- if ((track = GetAudioTrack(file)) >= 0)
+ tracks = MP4GetNumberOfTracks(file, NULL, 0);
+
+ if (tracks == 0)
{
- unsigned char *buff = NULL;
- int buff_size = 0;
- MP4GetTrackESConfiguration(file, track, &buff, &buff_size);
+ SetDlgItemText(hwndDlg, IDC_INFOTEXT, "No tracks found");
+ } else {
+ char *file_info;
+ char *info_text = malloc(1024*sizeof(char));
+ info_text[0] = '\0';
- if (buff)
+ for (i = 0; i < tracks; i++)
{
- AudioSpecificConfig(buff, &timeScale, &ch, &sf, &type,
- &dummy8, &dummy8, &dummy8, &dummy8);
- typeName = mpeg4AudioNames[type];
- free(buff);
-
- sprintf(info, "%d", ch);
- SetDlgItemText(hwndDlg, IDC_CHANNELS, info);
-
- sprintf(info, "%d Hz", timeScale);
- SetDlgItemText(hwndDlg, IDC_SAMPLERATE, info);
- } else {
- typeName = "Unknown";
- SetDlgItemText(hwndDlg, IDC_CHANNELS, "n/a");
- SetDlgItemText(hwndDlg, IDC_SAMPLERATE, "n/a");
+ file_info = MP4Info(file, i+1);
+ lstrcat(info_text, file_info);
}
- trackDuration = MP4GetTrackDuration(file, track);
+ SetDlgItemText(hwndDlg, IDC_INFOTEXT, info_text);
+ free(info_text);
+ }
- msDuration = MP4ConvertFromTrackDuration(file, track,
- trackDuration, MP4_MSECS_TIME_SCALE);
+ MP4Close(file);
- avgBitRate = MP4GetTrackIntegerProperty(file, track,
- "mdia.minf.stbl.stsd.mp4a.esds.decConfigDescr.avgBitrate");
+ return TRUE;
- SetDlgItemText(hwndDlg, IDC_TYPE, typeName);
-
- sprintf(info, "%.3f secs", (float)msDuration/1000.0);
- SetDlgItemText(hwndDlg, IDC_DURATION, info);
-
- sprintf(info, "%u Kbps", (avgBitRate+500)/1000);
- SetDlgItemText(hwndDlg, IDC_BITRATE, info);
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDCANCEL:
+ case IDOK:
+ EndDialog(hwndDlg, wParam);
+ return TRUE;
}
-
- if ((track = GetVideoTrack(file)) >= 0)
- {
- type = MP4GetTrackVideoType(file, track);
- typeName = "Unknown";
-
- if (type == MP4_MPEG4_VIDEO_TYPE) {
- type = MP4GetVideoProfileLevel(file);
- if (type > 0 && type <= numMpeg4VideoTypes) {
- typeName = mpeg4VideoNames[type - 1];
- } else {
- typeName = "MPEG-4";
- }
- } else {
- for (i = 0; i < numMpegVideoTypes; i++) {
- if (type == mpegVideoTypes[i]) {
- typeName = mpegVideoNames[i];
- break;
- }
- }
- }
+ }
+ return FALSE;
+}
+
+/* returns the name of the object type */
+char *get_ot_string(int ot)
+{
+ switch (ot)
+ {
+ case 0:
+ return "Main";
+ case 1:
+ return "LC";
+ case 2:
+ return "SSR";
+ case 3:
+ return "LTP";
+ }
+ return NULL;
+}
- trackDuration = MP4GetTrackDuration(file, track);
- msDuration = MP4ConvertFromTrackDuration(file, track,
- trackDuration, MP4_MSECS_TIME_SCALE);
+BOOL CALLBACK aac_info_dialog_proc(HWND hwndDlg, UINT message,
+ WPARAM wParam, LPARAM lParam)
+{
+ faadAACInfo aacInfo;
+ char *info_text;
- avgBitRate = MP4GetTrackIntegerProperty(file, track,
- "mdia.minf.stbl.stsd.mp4v.esds.decConfigDescr.avgBitrate");
+ switch (message) {
+ case WM_INITDIALOG:
+ info_text = malloc(1024*sizeof(char));
- // Note not all mp4 implementations set width and height correctly
- // The real answer can be buried inside the ES configuration info
- width = MP4GetTrackIntegerProperty(file, track,
- "mdia.minf.stbl.stsd.mp4v.width");
+ get_AAC_format(info_fn, &aacInfo, NULL, NULL, 0);
- height = MP4GetTrackIntegerProperty(file, track,
- "mdia.minf.stbl.stsd.mp4v.height");
+ sprintf(info_text, "%s AAC %s, %d sec, %d kbps, %d Hz",
+ (aacInfo.version==2)?"MPEG-2":"MPEG-4", get_ot_string(aacInfo.object_type),
+ aacInfo.length/1000, (int)(aacInfo.bitrate/1000.0+0.5), aacInfo.sampling_rate);
- // Note if variable rate video is being used the fps is an average
- numFrames = MP4GetTrackNumberOfSamples(file, track);
+ SetDlgItemText(hwndDlg, IDC_INFOTEXT, info_text);
- fps = ((float)numFrames/(float)msDuration) * 1000;
+ free(info_text);
- SetDlgItemText(hwndDlg, IDC_VTYPE, typeName);
-
- sprintf(info, "%.3f secs", (float)msDuration/1000.0);
- SetDlgItemText(hwndDlg, IDC_VDURATION, info);
-
- sprintf(info, "%u Kbps", (avgBitRate+500)/1000);
- SetDlgItemText(hwndDlg, IDC_VBITRATE, info);
-
- sprintf(info, "%dx%d", width, height);
- SetDlgItemText(hwndDlg, IDC_VSIZE, info);
-
- sprintf(info, "%.2f", fps);
- SetDlgItemText(hwndDlg, IDC_VFPS, info);
- }
-
- MP4Close(file);
-
return TRUE;
case WM_COMMAND:
@@ -372,11 +264,10 @@
{
if(StringComp(fn + strlen(fn) - 3, "aac", 3) == 0)
{
- MessageBox(hwndParent,
- "Sorry, no support for AAC info.\n"
- "AudioCoding.com MPEG-4 General Audio player.",
- "About",
- MB_OK);
+ lstrcpy(info_fn, fn);
+
+ DialogBox(module.hDllInstance, MAKEINTRESOURCE(IDD_INFO),
+ hwndParent, aac_info_dialog_proc);
} else {
lstrcpy(info_fn, fn);
@@ -465,16 +356,21 @@
int maxlatency;
int thread_id;
int avg_bitrate;
- void *sample_buffer;
unsigned char *buffer;
int buffer_size;
- faacDecFrameInfo frameInfo;
faacDecConfigurationPtr config;
mp4state.channels = 0;
mp4state.samplerate = 0;
mp4state.filetype = 0;
+ mp4state.seek_table_len = 0;
+ if (mp4state.seek_table)
+ {
+ free(mp4state.seek_table);
+ mp4state.seek_table = NULL;
+ }
+
strcpy(mp4state.filename, fn);
if(StringComp(fn + strlen(fn) - 3, "aac", 3) == 0)
@@ -491,7 +387,10 @@
{
long pos, tmp, read;
- mp4state.aacfile = fopen(fn, "rb");
+ get_AAC_format(mp4state.filename, &mp4state.aacInfo,
+ &mp4state.seek_table, &mp4state.seek_table_len, 1);
+
+ mp4state.aacfile = fopen(mp4state.filename, "rb");
if (!mp4state.aacfile)
{
show_error(module.hMainWindow, "Unable to open file.");
@@ -504,7 +403,7 @@
mp4state.filesize = ftell(mp4state.aacfile);
fseek(mp4state.aacfile, pos, SEEK_SET);
- if(!(mp4state.buffer=(unsigned char*)malloc(768*48)))
+ if (!(mp4state.buffer=(unsigned char*)malloc(768*48)))
{
show_error(module.hMainWindow, "Memory allocation error.");
faacDecClose(mp4state.hDecoder);
@@ -513,12 +412,12 @@
}
memset(mp4state.buffer, 0, 768*48);
- if(mp4state.filesize < 768*48)
+ if (mp4state.filesize < 768*48)
tmp = mp4state.filesize;
else
tmp = 768*48;
read = fread(mp4state.buffer, 1, tmp, mp4state.aacfile);
- if(read == tmp)
+ if (read == tmp)
{
mp4state.bytes_read = read;
mp4state.bytes_into_buffer = read;
@@ -529,7 +428,7 @@
return -1;
}
- if((mp4state.bytes_consumed=faacDecInit(mp4state.hDecoder,
+ if ((mp4state.bytes_consumed=faacDecInit(mp4state.hDecoder,
mp4state.buffer, &mp4state.samplerate, &mp4state.channels)) < 0)
{
show_error(module.hMainWindow, "Can't initialize library.");
@@ -539,11 +438,14 @@
}
mp4state.bytes_into_buffer -= mp4state.bytes_consumed;
- avg_bitrate = 0;
+ avg_bitrate = mp4state.aacInfo.bitrate;
- module.is_seekable = 0;
+ if (mp4state.aacInfo.headertype == 2)
+ module.is_seekable = 1;
+ else
+ module.is_seekable = 0;
} else {
- mp4state.mp4file = MP4Read(fn, 0);
+ mp4state.mp4file = MP4Read(mp4state.filename, 0);
if (!mp4state.mp4file)
{
show_error(module.hMainWindow, "Unable to open file.");
@@ -701,6 +603,14 @@
fclose(mp4state.aacfile);
else
MP4Close(mp4state.mp4file);
+
+ if (mp4state.seek_table)
+ {
+ free(mp4state.seek_table);
+ mp4state.seek_table = NULL;
+ mp4state.seek_table_len = 0;
+ }
+
module.outMod->Close();
module.SAVSADeInit();
}
@@ -731,9 +641,14 @@
length, MP4_MSECS_TIME_SCALE);
MP4Close(file);
- }
- return msDuration;
+ return msDuration;
+ } else {
+ faadAACInfo aacInfo;
+ get_AAC_format(fn, &aacInfo, NULL, NULL, 0);
+
+ return aacInfo.length;
+ }
}
int getlength()
@@ -755,6 +670,8 @@
length, MP4_MSECS_TIME_SCALE);
return msDuration;
+ } else {
+ return mp4state.aacInfo.length;
}
return 0;
}
@@ -781,9 +698,7 @@
char *tmp = PathFindFileName(mp4state.filename);
strcpy(title, tmp);
}
- }
- else /* some other file */
- {
+ } else {
if (length_in_ms)
*length_in_ms = getsonglength(filename);
@@ -799,8 +714,6 @@
{
}
-int last_frame;
-
DWORD WINAPI MP4PlayThread(void *b)
{
int done = 0;
@@ -812,7 +725,7 @@
faacDecFrameInfo frameInfo;
PlayThreadAlive = 1;
- last_frame = 0;
+ mp4state.last_frame = 0;
while (!*((int *)b))
{
@@ -843,11 +756,10 @@
}
Sleep(10);
- }
- else if (module.outMod->CanWrite() >=
+ } else if (module.outMod->CanWrite() >=
((1024*mp4state.channels*sizeof(short))<<(module.dsp_isactive()?1:0)))
{
- if(last_frame)
+ if (mp4state.last_frame)
{
done = 1;
} else {
@@ -862,7 +774,7 @@
NULL, NULL, NULL, NULL);
if (rc == 0 || buffer == NULL)
{
- last_frame = 1;
+ mp4state.last_frame = 1;
sample_buffer = NULL;
frameInfo.samples = 0;
} else {
@@ -871,15 +783,23 @@
if (frameInfo.error > 0)
{
show_error(module.hMainWindow, faacDecGetErrorMessage(frameInfo.error));
- last_frame = 1;
+ mp4state.last_frame = 1;
}
if (mp4state.sampleId >= mp4state.numSamples)
- last_frame = 1;
+ mp4state.last_frame = 1;
if (buffer) free(buffer);
if (!killPlayThread && (frameInfo.samples > 0))
{
+ if (res_table[m_resolution] == 24)
+ {
+ /* convert libfaad output (3 bytes packed in 4) */
+ char *temp_buffer = convert3in4to3in3(sample_buffer, frameInfo.samples);
+ memcpy((void*)sample_buffer, (void*)temp_buffer, frameInfo.samples*3);
+ free(temp_buffer);
+ }
+
module.SAAddPCMData(sample_buffer, mp4state.channels, res_table[m_resolution],
mp4state.decode_pos_ms);
module.VSAAddPCMData(sample_buffer, mp4state.channels, res_table[m_resolution],
@@ -909,6 +829,23 @@
return 0;
}
+int aac_seek(int pos_ms)
+{
+ int read;
+ int offset_sec = (int)((float)pos_ms / 1000.0 + 0.5);
+
+ fseek(mp4state.aacfile, mp4state.seek_table[offset_sec], SEEK_SET);
+
+ mp4state.bytes_read = mp4state.seek_table[offset_sec];
+ mp4state.bytes_consumed = 0;
+
+ read = fread(mp4state.buffer, 1, 768*48, mp4state.aacfile);
+ mp4state.bytes_read += read;
+ mp4state.bytes_into_buffer = read;
+
+ return 0;
+}
+
DWORD WINAPI AACPlayThread(void *b)
{
int done = 0;
@@ -918,10 +855,23 @@
faacDecFrameInfo frameInfo;
PlayThreadAlive = 1;
- last_frame = 0;
+ mp4state.last_frame = 0;
while (!*((int *)b))
{
+ /* seeking */
+ if (mp4state.seek_needed != -1)
+ {
+ int ms;
+
+ /* Round off to a second */
+ ms = mp4state.seek_needed - (mp4state.seek_needed%1000);
+ module.outMod->Flush(mp4state.decode_pos_ms);
+ aac_seek(ms);
+ mp4state.decode_pos_ms = ms;
+ mp4state.seek_needed = -1;
+ }
+
if (done)
{
module.outMod->CanWrite();
@@ -934,11 +884,10 @@
}
Sleep(10);
- }
- else if (module.outMod->CanWrite() >=
+ } else if (module.outMod->CanWrite() >=
((1024*mp4state.channels*sizeof(short))<<(module.dsp_isactive()?1:0)))
{
- if(last_frame)
+ if (mp4state.last_frame)
{
done = 1;
} else {
@@ -947,7 +896,7 @@
do
{
- if (mp4state.bytes_consumed>0)
+ if (mp4state.bytes_consumed > 0)
{
if (mp4state.bytes_into_buffer)
{
@@ -983,9 +932,9 @@
if (mp4state.bytes_read < mp4state.filesize)
{
show_error(module.hMainWindow, faacDecGetErrorMessage(frameInfo.error));
- last_frame = 1;
+ mp4state.last_frame = 1;
} else {
- last_frame = 1;
+ mp4state.last_frame = 1;
}
}
@@ -997,6 +946,14 @@
if (!killPlayThread && (frameInfo.samples > 0))
{
+ if (res_table[m_resolution] == 24)
+ {
+ /* convert libfaad output (3 bytes packed in 4 bytes) */
+ char *temp_buffer = convert3in4to3in3(sample_buffer, frameInfo.samples);
+ memcpy((void*)sample_buffer, (void*)temp_buffer, frameInfo.samples*3);
+ free(temp_buffer);
+ }
+
module.SAAddPCMData(sample_buffer, mp4state.channels, res_table[m_resolution],
mp4state.decode_pos_ms);
module.VSAAddPCMData(sample_buffer, mp4state.channels, res_table[m_resolution],
@@ -1021,6 +978,13 @@
}
}
+ if (mp4state.seek_table)
+ {
+ free(mp4state.seek_table);
+ mp4state.seek_table = NULL;
+ mp4state.seek_table_len = 0;
+ }
+
PlayThreadAlive = 0;
return 0;
@@ -1029,7 +993,7 @@
static In_Module module =
{
IN_VER,
- "AudioCoding.com MPEG-4 General Audio player: " __DATE__,
+ "AudioCoding.com MPEG-4 General Audio player: " FAAD2_VERSION,
0, // hMainWindow
0, // hDllInstance
"MP4\0MPEG-4 Files (*.MP4)\0AAC\0AAC Files (*.AAC)\0"
--- a/plugins/in_mp4/in_mp4.dsp
+++ b/plugins/in_mp4/in_mp4.dsp
@@ -92,6 +92,10 @@
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
+SOURCE=.\aacinfo.c
+# End Source File
+# Begin Source File
+
SOURCE=.\config.c
# End Source File
# Begin Source File
@@ -106,6 +110,10 @@
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\aacinfo.h
+# End Source File
# Begin Source File
SOURCE=.\config.h
--- a/plugins/in_mp4/in_mp4.rc
+++ b/plugins/in_mp4/in_mp4.rc
@@ -1,4 +1,4 @@
-//Microsoft Developer Studio generated resource script.
+// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
@@ -27,18 +27,18 @@
// TEXTINCLUDE
//
-1 TEXTINCLUDE DISCARDABLE
+1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
-2 TEXTINCLUDE DISCARDABLE
+2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
-3 TEXTINCLUDE DISCARDABLE
+3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
@@ -52,58 +52,43 @@
// Dialog
//
-IDD_INFO DIALOG DISCARDABLE 0, 0, 191, 207
-STYLE DS_MODALFRAME | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
+IDD_INFO DIALOGEX 0, 0, 303, 207
+STYLE DS_SETFONT | DS_MODALFRAME | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION |
+ WS_SYSMENU
CAPTION "MPEG-4 File Info"
-FONT 8, "MS Sans Serif"
+FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
- DEFPUSHBUTTON "OK",IDOK,134,186,50,14
- LTEXT "Type:",IDC_STATIC,14,22,19,8
- LTEXT "Average bitrate:",IDC_STATIC,14,48,51,8
- LTEXT "Duration:",IDC_STATIC,14,35,30,8
- LTEXT "Samplerate:",IDC_STATIC,14,61,38,8
- GROUPBOX "MPEG-4 Audio Track",IDC_STATIC,7,7,177,84
- LTEXT "n/a",IDC_TYPE,71,22,102,8
- LTEXT "n/a",IDC_BITRATE,71,48,102,8
- LTEXT "n/a",IDC_DURATION,71,35,102,8
- LTEXT "n/a",IDC_SAMPLERATE,71,61,102,8
- LTEXT "Type:",IDC_STATIC,14,113,19,8
- LTEXT "Average bitrate:",IDC_STATIC,14,139,51,8
- LTEXT "Duration:",IDC_STATIC,14,126,30,8
- LTEXT "Size:",IDC_STATIC,14,152,16,8
- GROUPBOX "MPEG-4 Video Track",IDC_STATIC,7,98,177,84
- LTEXT "n/a",IDC_VTYPE,71,113,102,8
- LTEXT "n/a",IDC_VBITRATE,71,139,102,8
- LTEXT "n/a",IDC_VDURATION,71,126,102,8
- LTEXT "n/a",IDC_VSIZE,71,152,102,8
- LTEXT "Frames/second:",IDC_STATIC,14,165,52,8
- LTEXT "n/a",IDC_VFPS,71,165,102,8
- LTEXT "Channels:",IDC_STATIC,14,74,32,8
- LTEXT "n/a",IDC_CHANNELS,71,74,102,8
+ DEFPUSHBUTTON "OK",IDOK,246,186,50,14
+ LTEXT "Static",IDC_INFOTEXT,14,17,275,47,0,WS_EX_CLIENTEDGE
+ GROUPBOX "Track info",IDC_STATIC,7,7,289,64
+ GROUPBOX "User data",IDC_STATIC,7,77,289,104
END
-IDD_CONFIG DIALOG DISCARDABLE 0, 0, 125, 95
-STYLE DS_MODALFRAME | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
+IDD_CONFIG DIALOGEX 0, 0, 151, 108
+STYLE DS_SETFONT | DS_MODALFRAME | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION |
+ WS_SYSMENU
CAPTION "Configuration"
-FONT 8, "MS Sans Serif"
+FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
CONTROL "Slider1",IDC_PRIORITY,"msctls_trackbar32",TBS_VERT |
- TBS_NOTICKS | WS_TABSTOP,13,15,18,39
+ TBS_NOTICKS | WS_TABSTOP,13,15,18,46
CONTROL "16 bits",IDC_16BITS,"Button",BS_AUTORADIOBUTTON,77,18,
37,10
- CONTROL "24 bits",IDC_24BITS,"Button",BS_AUTORADIOBUTTON |
- WS_DISABLED,77,30,37,10
- CONTROL "32 bits",IDC_32BITS,"Button",BS_AUTORADIOBUTTON,77,42,
+ CONTROL "24 bits",IDC_24BITS,"Button",BS_AUTORADIOBUTTON,77,40,
37,10
+ CONTROL "32 bits",IDC_32BITS,"Button",BS_AUTORADIOBUTTON,77,51,
+ 37,10
CONTROL "Show errors",IDC_ERROR,"Button",BS_AUTOCHECKBOX |
- WS_TABSTOP,7,60,53,10
- DEFPUSHBUTTON "OK",IDOK,68,74,50,14
- PUSHBUTTON "Cancel",IDCANCEL,7,74,50,14
- GROUPBOX "Priority",IDC_STATIC,7,7,57,49
+ WS_TABSTOP,7,70,53,10
+ DEFPUSHBUTTON "OK",IDOK,94,87,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,7,87,50,14
+ GROUPBOX "Priority",IDC_STATIC,7,7,57,58
LTEXT "Highest",IDC_STATIC,34,18,25,8
- LTEXT "Normal",IDC_STATIC,34,29,23,8
- LTEXT "Lowest",IDC_STATIC,34,40,24,8
- GROUPBOX "Resolution",IDC_STATIC,71,7,47,49
+ LTEXT "Normal",IDC_STATIC,34,35,23,8
+ LTEXT "Lowest",IDC_STATIC,34,52,24,8
+ GROUPBOX "Resolution",IDC_STATIC,71,7,73,58
+ CONTROL "16 bits dithered",IDC_16BITS_DITHERED,"Button",
+ BS_AUTORADIOBUTTON,77,29,64,10
END
@@ -113,12 +98,12 @@
//
#ifdef APSTUDIO_INVOKED
-GUIDELINES DESIGNINFO DISCARDABLE
+GUIDELINES DESIGNINFO
BEGIN
IDD_INFO, DIALOG
BEGIN
LEFTMARGIN, 7
- RIGHTMARGIN, 184
+ RIGHTMARGIN, 296
TOPMARGIN, 7
BOTTOMMARGIN, 200
END
@@ -126,9 +111,9 @@
IDD_CONFIG, DIALOG
BEGIN
LEFTMARGIN, 7
- RIGHTMARGIN, 118
+ RIGHTMARGIN, 144
TOPMARGIN, 7
- BOTTOMMARGIN, 88
+ BOTTOMMARGIN, 101
END
END
#endif // APSTUDIO_INVOKED
--- a/plugins/in_mp4/in_mp4.vcproj
+++ b/plugins/in_mp4/in_mp4.vcproj
@@ -135,6 +135,9 @@
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
<File
+ RelativePath="aacinfo.c">
+ </File>
+ <File
RelativePath=".\config.c">
</File>
<File
@@ -148,6 +151,9 @@
Name="Header Files"
Filter="h;hpp;hxx;hm;inl">
<File
+ RelativePath="aacinfo.h">
+ </File>
+ <File
RelativePath=".\config.h">
</File>
<File
@@ -158,6 +164,9 @@
</File>
<File
RelativePath=".\out.h">
+ </File>
+ <File
+ RelativePath="resource.h">
</File>
<File
RelativePath=".\utils.h">
--- a/plugins/in_mp4/resource.h
+++ b/plugins/in_mp4/resource.h
@@ -1,10 +1,11 @@
//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
+// Microsoft Visual C++ generated include file.
// Used by in_mp4.rc
//
#define IDD_INFO 101
#define IDD_CONFIG 102
#define IDC_TYPE 1000
+#define IDC_INFOTEXT 1000
#define IDC_DURATION 1001
#define IDC_BITRATE 1002
#define IDC_SAMPLERATE 1003
@@ -19,6 +20,8 @@
#define IDC_VFPS 1008
#define IDC_32BITS 1008
#define IDC_CHANNELS 1009
+#define IDC_24BITS2 1009
+#define IDC_16BITS_DITHERED 1009
// Next default values for new objects
//
--- a/plugins/in_mp4/utils.c
+++ b/plugins/in_mp4/utils.c
@@ -16,7 +16,7 @@
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
-** $Id: utils.c,v 1.1 2002/08/09 21:48:12 menno Exp $
+** $Id: utils.c,v 1.2 2002/08/14 17:55:20 menno Exp $
**/
#define WIN32_LEAN_AND_MEAN
@@ -130,4 +130,20 @@
}
return (LPTSTR)pT; // const -> non const
+}
+
+char *convert3in4to3in3(void *sample_buffer, int samples)
+{
+ int i;
+ long *sample_buffer24 = (long*)sample_buffer;
+ char *data = malloc(samples*3*sizeof(char));
+
+ for (i = 0; i < samples; i++)
+ {
+ data[i*3] = sample_buffer24[i] & 0xFF;
+ data[i*3+1] = (sample_buffer24[i] >> 8) & 0xFF;
+ data[i*3+2] = (sample_buffer24[i] >> 16) & 0xFF;
+ }
+
+ return data;
}
--- a/plugins/in_mp4/utils.h
+++ b/plugins/in_mp4/utils.h
@@ -16,11 +16,19 @@
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
-** $Id: utils.h,v 1.1 2002/08/09 21:48:12 menno Exp $
+** $Id: utils.h,v 1.2 2002/08/14 17:55:20 menno Exp $
**/
+#ifndef UTILS_INCLUDED
+#define UTILS_INCLUDED
+
+#include <mp4.h>
+
LPTSTR PathFindFileName(LPCTSTR pPath);
int GetVideoTrack(MP4FileHandle infile);
int GetAudioTrack(MP4FileHandle infile);
int GetAACTrack(MP4FileHandle infile);
int StringComp(char const *str1, char const *str2, unsigned long len);
+char *convert3in4to3in3(void *sample_buffer, int samples);
+
+#endif
\ No newline at end of file