[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;
}