[MPlayer-dev-eng] [PATCH] audio support for avisynth scripts
Gianluigi Tiesi
mplayer at netfarm.it
Sun Mar 4 01:48:56 CET 2007
I've used a specific tool to reduce differences,
I'm not able to do better ;)
Regards
--
Gianluigi Tiesi <sherpya at netfarm.it>
EDP Project Leader
Netfarm S.r.l. - http://www.netfarm.it/
Free Software: http://oss.netfarm.it/
-------------- next part --------------
--- main/libmpdemux/demux_avs.c 2006-09-02 02:58:56.311185600 +0200
+++ sherpya/libmpdemux/demux_avs.c 2007-03-04 01:29:00.762288000 +0100
@@ -40,7 +40,6 @@
#include "demux_avs.h"
#define MAX_AVS_SIZE 16 * 1024 /* 16k should be enough */
-#undef ENABLE_AUDIO
HMODULE WINAPI LoadLibraryA(LPCSTR);
FARPROC WINAPI GetProcAddress(HMODULE,LPCSTR);
@@ -53,10 +52,7 @@
typedef WINAPI void (*imp_avs_release_clip)(AVS_Clip *);
typedef WINAPI AVS_VideoFrame* (*imp_avs_get_frame)(AVS_Clip *, int n);
typedef WINAPI void (*imp_avs_release_video_frame)(AVS_VideoFrame *);
-#ifdef ENABLE_AUDIO
-//typedef WINAPI int (*imp_avs_get_audio)(AVS_Clip *, void * buf, uint64_t start, uint64_t count);
-typedef WINAPI int (*imp_avs_get_audio)(AVS_ScriptEnvironment *, void * buf, uint64_t start, uint64_t count);
-#endif
+typedef WINAPI int (*imp_avs_get_audio)(AVS_Clip *, void * buf, uint64_t start, uint64_t count);
#define Q(string) # string
#define IMPORT_FUNC(x) \
@@ -74,6 +70,7 @@
#endif
HMODULE dll;
int frameno;
+ uint64_t sampleno;
int init;
imp_avs_create_script_environment avs_create_script_environment;
@@ -83,9 +80,7 @@
imp_avs_release_clip avs_release_clip;
imp_avs_get_frame avs_get_frame;
imp_avs_release_video_frame avs_release_video_frame;
-#ifdef ENABLE_AUDIO
imp_avs_get_audio avs_get_audio;
-#endif
} AVS_T;
AVS_T *initAVS(const char *filename)
@@ -115,9 +110,7 @@
IMPORT_FUNC(avs_release_clip);
IMPORT_FUNC(avs_get_frame);
IMPORT_FUNC(avs_release_video_frame);
-#ifdef ENABLE_AUDIO
IMPORT_FUNC(avs_get_audio);
-#endif
AVS->avs_env = AVS->avs_create_script_environment(AVISYNTH_INTERFACE_VERSION);
if (!AVS->avs_env)
@@ -175,7 +168,10 @@
demux_stream_t *d_video=demuxer->video;
sh_video_t *sh_video=d_video->sh;
- if (avs_has_video(AVS->video_info))
+ demux_stream_t *d_audio=demuxer->audio;
+ sh_audio_t *sh_audio=d_audio->sh;
+
+ if (sh_video && ds == demuxer->video)
{
char *dst;
int w, h;
@@ -210,32 +206,73 @@
AVS->avs_release_video_frame(curr_frame);
}
-#ifdef ENABLE_AUDIO
/* Audio */
- if (avs_has_audio(AVS->video_info))
+ if (sh_audio && ds == demuxer->audio)
{
- demux_stream_t *d_audio=demuxer->audio;
- sh_audio_t *sh_audio=d_audio->sh;
- int l = sh_audio->wf->nAvgBytesPerSec;
+ if (AVS->sampleno >= AVS->video_info->num_audio_samples) return 0; // EOF
+
+ int read_samples = sh_audio->wf->nSamplesPerSec / 10; // return 0.1 sec of audio per request
+ if (read_samples <= 0) read_samples = 1; // < 10 samples per sec audio?
+
+ if (AVS->sampleno + (uint64_t) read_samples > AVS->video_info->num_audio_samples)
+ read_samples = AVS->video_info->num_audio_samples - AVS->sampleno;
+
+ int l = read_samples * sh_audio->wf->wBitsPerSample / 8 * sh_audio->wf->nChannels;
dp = new_demux_packet(l);
- if (AVS->avs_get_audio(AVS->avs_env, dp->buffer, AVS->frameno*sh_video->fps*l, l))
+ if (AVS->avs_get_audio(AVS->clip, dp->buffer, AVS->sampleno, (int64_t) read_samples))
{
mp_msg(MSGT_DEMUX, MSGL_V, "AVS: avs_get_audio() failed\n");
return 0;
}
+ dp->pts = (double) AVS->sampleno / (double) sh_audio->wf->nSamplesPerSec;
ds_add_packet(demuxer->audio, dp);
+ AVS->sampleno += read_samples;
}
-#endif
return 1;
}
+static int avs_get_audio_format(int format)
+{
+ switch (format)
+ {
+ case AVS_SAMPLE_INT8:
+ case AVS_SAMPLE_INT16:
+ case AVS_SAMPLE_INT24:
+ case AVS_SAMPLE_INT32:
+ return 0xfffe;
+ case AVS_SAMPLE_FLOAT:
+ return 0x3;
+ default:
+ return 0;
+ }
+}
+
+static int avs_get_audio_sample_size(int format)
+{
+ switch (format)
+ {
+ case AVS_SAMPLE_INT8:
+ return 1;
+ case AVS_SAMPLE_INT16:
+ return 2;
+ case AVS_SAMPLE_INT24:
+ return 3;
+ case AVS_SAMPLE_INT32:
+ case AVS_SAMPLE_FLOAT:
+ return 4;
+ default:
+ return 2;
+ }
+}
+
static demuxer_t* demux_open_avs(demuxer_t* demuxer)
{
int found = 0;
AVS_T *AVS = (AVS_T *) demuxer->priv;
AVS->frameno = 0;
+ AVS->sampleno = 0;
mp_msg(MSGT_DEMUX, MSGL_V, "AVS: demux_open_avs()\n");
demuxer->seekable = 1;
@@ -309,10 +346,14 @@
sh_video->num_frames_decoded = 0;
}
-#ifdef ENABLE_AUDIO
/* Audio */
- if (avs_has_audio(AVS->video_info))
+ if (avs_has_audio(AVS->video_info) && demuxer->audio->id != -2)
{
+ int audio_format = avs_get_audio_format(AVS->video_info->sample_type);
+
+ if (!audio_format) {
+ mp_msg(MSGT_DEMUX, MSGL_V, "AVS: Unknown audio sample type\n");
+ } else {
sh_audio_t *sh_audio = new_sh_audio(demuxer, 0);
found = 1;
mp_msg(MSGT_DEMUX, MSGL_V, "AVS: Clip has audio -> Channels = %d - Freq = %d\n", AVS->video_info->nchannels, AVS->video_info->audio_samples_per_second);
@@ -320,18 +361,19 @@
demuxer->audio->sh = sh_audio;
sh_audio->ds = demuxer->audio;
+ sh_audio->samplesize = avs_get_audio_sample_size(AVS->video_info->sample_type);
sh_audio->wf = (WAVEFORMATEX*) malloc(sizeof(WAVEFORMATEX));
- sh_audio->wf->wFormatTag = sh_audio->format = 0x1;
+ sh_audio->wf->wFormatTag = sh_audio->format = audio_format;
sh_audio->wf->nChannels = sh_audio->channels = AVS->video_info->nchannels;
sh_audio->wf->nSamplesPerSec = sh_audio->samplerate = AVS->video_info->audio_samples_per_second;
- sh_audio->wf->nAvgBytesPerSec = AVS->video_info->audio_samples_per_second * 4;
+ sh_audio->wf->nAvgBytesPerSec = AVS->video_info->audio_samples_per_second * AVS->video_info->nchannels * sh_audio->samplesize;
sh_audio->wf->nBlockAlign = 4;
- sh_audio->wf->wBitsPerSample = sh_audio->samplesize = 16; // AVS->video_info->sample_type ??
+ sh_audio->wf->wBitsPerSample = sh_audio->samplesize * 8;
sh_audio->wf->cbSize = 0;
sh_audio->i_bps = sh_audio->wf->nAvgBytesPerSec;
sh_audio->o_bps = sh_audio->wf->nAvgBytesPerSec;
}
-#endif
+ }
AVS->init = 1;
if (found)
@@ -343,21 +385,30 @@
static int demux_avs_control(demuxer_t *demuxer, int cmd, void *arg)
{
demux_stream_t *d_video=demuxer->video;
+ demux_stream_t *d_audio=demuxer->audio;
sh_video_t *sh_video=d_video->sh;
+ sh_audio_t *sh_audio=d_audio->sh;
AVS_T *AVS = (AVS_T *) demuxer->priv;
+ double video_len, audio_len;
switch(cmd)
{
case DEMUXER_CTRL_GET_TIME_LENGTH:
{
- if (!AVS->video_info->num_frames) return DEMUXER_CTRL_DONTKNOW;
- *((double *)arg) = (double)AVS->video_info->num_frames / sh_video->fps;
+ if (!AVS->video_info->num_frames && !AVS->video_info->num_audio_samples) return DEMUXER_CTRL_DONTKNOW;
+ video_len = sh_video ? (double)AVS->video_info->num_frames / sh_video->fps : 0.0;
+ audio_len = sh_audio ? (double)AVS->video_info->num_audio_samples / (double)sh_audio->samplerate : 0.0;
+ *((double *)arg) = FFMAX(video_len, audio_len);
return DEMUXER_CTRL_OK;
}
case DEMUXER_CTRL_GET_PERCENT_POS:
{
- if (!AVS->video_info->num_frames) return DEMUXER_CTRL_DONTKNOW;
+ if (AVS->video_info->num_frames)
*((int *)arg) = (int) (AVS->frameno * 100 / AVS->video_info->num_frames);
+ else if (AVS->video_info->num_audio_samples)
+ *((int *)arg) = (int) (AVS->sampleno * 100 / AVS->video_info->num_audio_samples);
+ else
+ return DEMUXER_CTRL_DONTKNOW;
return DEMUXER_CTRL_OK;
}
default:
@@ -389,22 +440,33 @@
{
demux_stream_t *d_video=demuxer->video;
sh_video_t *sh_video=d_video->sh;
+ demux_stream_t *d_audio=demuxer->audio;
+ sh_audio_t *sh_audio=d_audio->sh;
AVS_T *AVS = (AVS_T *) demuxer->priv;
- int video_pos=AVS->frameno;
+ double position = 0.0;
+
+ if (! flags&1) { // seek relative
+ if (sh_video)
+ position = (double)AVS->frameno / sh_video->fps;
+ else if (sh_audio)
+ position = (double)AVS->sampleno / sh_audio->wf->nSamplesPerSec;
+ }
//mp_msg(MSGT_DEMUX, MSGL_V, "AVS: seek rel_seek_secs = %f - flags = %x\n", rel_seek_secs, flags);
- // seek absolute
- if (flags&1) video_pos=0;
- video_pos += (rel_seek_secs * sh_video->fps);
- if (video_pos < 0) video_pos = 0;
- if (video_pos > AVS->video_info->num_frames) video_pos = AVS->video_info->num_frames;
+ position += rel_seek_secs;
+
+ if (sh_video) {
+ AVS->frameno = position * ((double) AVS->video_info->fps_numerator / (double) AVS->video_info->fps_denominator);
+ sh_video->num_frames_decoded = AVS->frameno;
+ sh_video->num_frames = AVS->frameno;
+ d_video->pts = position;
+ }
+
+ if (sh_audio)
+ AVS->sampleno = (position + audio_delay) * (double) sh_audio->wf->nSamplesPerSec;
- AVS->frameno = video_pos;
- sh_video->num_frames_decoded = video_pos;
- sh_video->num_frames = video_pos;
- d_video->pts=AVS->frameno / sh_video->fps; // OSD
}
static int avs_check_file(demuxer_t *demuxer)
More information about the MPlayer-dev-eng
mailing list