[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