Web lists-archives.com

[MPlayer-dev-eng] [PATCH v2] Determine replay gain




Improved and extended to demuxer lavf.

Ingo
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;
     }
_______________________________________________
MPlayer-dev-eng mailing list
MPlayer-dev-eng@xxxxxxxxxxxx
https://lists.mplayerhq.hu/mailman/listinfo/mplayer-dev-eng