[PATCH v2] Determine replay gain

Ingo Brückl <[email protected]>
Newsgroups gmane.comp.video.mplayer.devel
Message-ID <[email protected]>
Improved and extended to demuxer lavf.

Ingo

_______________________________________________
MPlayer-dev-eng mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/mplayer-dev-eng
replay_gain_v2.patch (text/x-diff, 4.8 KB)
Index: libmpdemux/demuxer.h
===================================================================
--- libmpdemux/demuxer.h	(revision 37922)
+++ libmpdemux/demuxer.h	(working copy)
@@ -110,6 +110,7 @@
 #define DEMUXER_CTRL_SWITCH_VIDEO 14
 #define DEMUXER_CTRL_IDENTIFY_PROGRAM 15
 #define DEMUXER_CTRL_CORRECT_PTS 16
+#define DEMUXER_CTRL_GET_REPLAY_GAIN 17
 
 #define SEEK_ABSOLUTE (1 << 0)
 #define SEEK_FACTOR   (1 << 1)
Index: libmpdemux/demux_audio.c
===================================================================
--- libmpdemux/demux_audio.c	(revision 37922)
+++ libmpdemux/demux_audio.c	(working copy)
@@ -45,6 +45,7 @@
 typedef struct da_priv {
   int frmt;
   double next_pts;
+  int r_gain;
 } da_priv_t;
 
 //! rather arbitrary value for maximum length of wav-format headers
@@ -285,7 +286,7 @@
  *
  * @return 0 (error or no variable bitrate mode) or number of frames
  */
-static unsigned int mp3_vbr_frames(stream_t *s, off_t off) {
+static unsigned int mp3_vbr_frames(stream_t *s, off_t off, da_priv_t *priv) {
   static const int xing_offset[2][2] = {{32, 17}, {17, 9}};
   unsigned int data;
   unsigned char hdr[4];
@@ -317,7 +318,25 @@
       data = stream_read_dword(s);
 
       if (data & 0x1)                   // frames field is present
-        return stream_read_dword(s);    // frames
+        data = stream_read_dword(s);    // frames
+
+      if (stream_skip(s, 108)) {
+        unsigned int dword = stream_read_dword(s);
+
+        if (dword == MKBETAG('L','A','M','E') && stream_skip(s, 11)) {
+          uint16_t word = stream_read_word(s);
+
+          /* Radio ReplayGain */
+          if ((word >> 13) == 1) {
+            priv->r_gain = word & 0x1ff;
+
+            if ((word >> 9) & 1)
+              priv->r_gain = -priv->r_gain;
+          }
+        }
+      }
+
+      return data;
     }
 
     /* VBRI (at fixed position: 32 bytes after header) */
@@ -436,6 +455,9 @@
 
   sh_audio = new_sh_audio(demuxer,0, NULL);
 
+  priv = malloc(sizeof(da_priv_t));
+  priv->r_gain = INT32_MIN;
+
   switch(frmt) {
   case MP3:
     sh_audio->format = (mp3_found->mpa_layer < 3 ? 0x50 : 0x55);
@@ -453,7 +475,7 @@
     sh_audio->wf->nBlockAlign = mp3_found->mpa_spf;
     sh_audio->wf->wBitsPerSample = 16;
     sh_audio->wf->cbSize = 0;
-    duration = (double) mp3_vbr_frames(s, demuxer->movi_start) * mp3_found->mpa_spf / mp3_found->mp3_freq;
+    duration = (double) mp3_vbr_frames(s, demuxer->movi_start, priv) * mp3_found->mpa_spf / mp3_found->mp3_freq;
     free(mp3_found);
     mp3_found = NULL;
     if(demuxer->movi_end && (s->flags & MP_STREAM_SEEK) == MP_STREAM_SEEK) {
@@ -645,7 +667,6 @@
 	    } break;
   }
 
-  priv = malloc(sizeof(da_priv_t));
   priv->frmt = frmt;
   priv->next_pts = 0;
   demuxer->priv = priv;
@@ -836,6 +857,11 @@
     	    *((int *)arg)=(int)( (priv->next_pts*100)  / audio_length);
 	    return DEMUXER_CTRL_OK;
 
+	case DEMUXER_CTRL_GET_REPLAY_GAIN:
+	    if (priv->r_gain == INT32_MIN) return DEMUXER_CTRL_DONTKNOW;
+	    *((int *)arg) = priv->r_gain;
+	    return DEMUXER_CTRL_OK;
+
 	default:
 	    return DEMUXER_CTRL_NOTIMPL;
     }
Index: libmpdemux/demux_lavf.c
===================================================================
--- libmpdemux/demux_lavf.c	(revision 37922)
+++ libmpdemux/demux_lavf.c	(working copy)
@@ -42,6 +42,7 @@
 #include "libavutil/avstring.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/opt.h"
+#include "libavutil/replaygain.h"
 
 #include "mp_taglists.h"
 
@@ -80,6 +81,7 @@
     int cur_program;
     int nb_streams_last;
     int use_lavf_netstream;
+    int r_gain;
 }lavf_priv_t;
 
 static int mp_read(void *opaque, uint8_t *buf, int size) {
@@ -155,8 +157,10 @@
     int read_size = INITIAL_PROBE_SIZE;
     int score;
 
-    if(!demuxer->priv)
+    if(!demuxer->priv) {
         demuxer->priv=calloc(sizeof(lavf_priv_t),1);
+        ((lavf_priv_t *)demuxer->priv)->r_gain = INT32_MIN;
+    }
     priv= demuxer->priv;
 
     init_avformat();
@@ -358,6 +362,14 @@
             }
             if (demuxer->audio->id != i)
                 st->discard= AVDISCARD_ALL;
+            if (priv->audio_streams == 0) {
+                int rg_size;
+                AVReplayGain *rg = (AVReplayGain*)av_stream_get_side_data(st, AV_PKT_DATA_REPLAYGAIN, &rg_size);
+                if (rg && rg_size >= sizeof(*rg)) {
+                    priv->r_gain = rg->track_gain / 10000;
+                }
+            } else
+                priv->r_gain = INT32_MIN;
             stream_id = priv->audio_streams++;
             break;
         }
@@ -903,6 +915,11 @@
             priv->cur_program = prog->progid = program->id;
             return DEMUXER_CTRL_OK;
         }
+        case DEMUXER_CTRL_GET_REPLAY_GAIN:
+            if (priv->r_gain == INT32_MIN)
+                return DEMUXER_CTRL_DONTKNOW;
+            *((int *)arg) = priv->r_gain;
+            return DEMUXER_CTRL_OK;
 	default:
 	    return DEMUXER_CTRL_NOTIMPL;
     }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.