* commit '5a7e35dd2351c30bab45177b9482cb8833a0ca78': Add replaygain side data type and code for parsing replaygain tags. Conflicts: libavcodec/avcodec.h libavcodec/version.h libavutil/version.h Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n2.3
| @@ -15,6 +15,13 @@ libavutil: 2012-10-22 | |||
| API changes, most recent first: | |||
| 2014-02-xx - xxxxxxx - lavu 53.07.0 - frame.h, replaygain.h | |||
| Add AV_FRAME_DATA_REPLAYGAIN for exporting replaygain tags. | |||
| Add a new header replaygain.h with the AVReplayGain struct. | |||
| 2014-02-xx - xxxxxxx - lavc 55.36.0 - avcodec.h | |||
| Add AV_PKT_DATA_REPLAYGAIN for exporting replaygain tags. | |||
| 2014-02-xx - xxxxxxx - lavf 55.13.0 - avformat.h | |||
| Add AVStream.side_data and AVStream.nb_side_data for exporting stream-global | |||
| side data (e.g. replaygain tags, video rotation) | |||
| @@ -1002,6 +1002,12 @@ enum AVPacketSideDataType { | |||
| */ | |||
| AV_PKT_DATA_H263_MB_INFO, | |||
| /** | |||
| * This side data should be associated with an audio stream and contains | |||
| * ReplayGain information in form of the AVReplayGain struct. | |||
| */ | |||
| AV_PKT_DATA_REPLAYGAIN, | |||
| /** | |||
| * Recommmends skipping the specified number of samples | |||
| * @code | |||
| @@ -29,7 +29,7 @@ | |||
| #include "libavutil/version.h" | |||
| #define LIBAVCODEC_VERSION_MAJOR 55 | |||
| #define LIBAVCODEC_VERSION_MINOR 53 | |||
| #define LIBAVCODEC_VERSION_MINOR 54 | |||
| #define LIBAVCODEC_VERSION_MICRO 100 | |||
| #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ | |||
| @@ -0,0 +1,154 @@ | |||
| /* | |||
| * This file is part of FFmpeg. | |||
| * | |||
| * FFmpeg is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation; either | |||
| * version 2.1 of the License, or (at your option) any later version. | |||
| * | |||
| * FFmpeg is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| * Lesser General Public License for more details. | |||
| * | |||
| * You should have received a copy of the GNU Lesser General Public | |||
| * License along with FFmpeg; if not, write to the Free Software | |||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| /** | |||
| * @file | |||
| * replaygain tags parsing | |||
| */ | |||
| #include <stdint.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "libavutil/avstring.h" | |||
| #include "libavutil/dict.h" | |||
| #include "libavutil/intreadwrite.h" | |||
| #include "libavutil/mathematics.h" | |||
| #include "libavutil/mem.h" | |||
| #include "libavutil/replaygain.h" | |||
| #include "avformat.h" | |||
| #include "replaygain.h" | |||
| static int32_t parse_gain(const char *gain) | |||
| { | |||
| char *fraction; | |||
| int scale = 10000; | |||
| int32_t mb = 0; | |||
| int db; | |||
| if (!gain) | |||
| return INT32_MIN; | |||
| gain += strspn(gain, " \t"); | |||
| db = strtol(gain, &fraction, 0); | |||
| if (*fraction++ == '.') { | |||
| while (av_isdigit(*fraction) && scale) { | |||
| mb += scale * (*fraction - '0'); | |||
| scale /= 10; | |||
| fraction++; | |||
| } | |||
| } | |||
| if (abs(db) > (INT32_MAX - mb) / 100000) | |||
| return INT32_MIN; | |||
| return db * 100000 + FFSIGN(db) * mb; | |||
| } | |||
| static uint32_t parse_peak(const uint8_t *peak) | |||
| { | |||
| int64_t val = 0; | |||
| int64_t scale = 1; | |||
| if (!peak) | |||
| return 0; | |||
| peak += strspn(peak, " \t"); | |||
| if (peak[0] == '1' && peak[1] == '.') | |||
| return UINT32_MAX; | |||
| else if (!(peak[0] == '0' && peak[1] == '.')) | |||
| return 0; | |||
| peak += 2; | |||
| while (av_isdigit(*peak)) { | |||
| int digit = *peak - '0'; | |||
| if (scale > INT64_MAX / 10) | |||
| break; | |||
| val = 10 * val + digit; | |||
| scale *= 10; | |||
| peak++; | |||
| } | |||
| return av_rescale(val, UINT32_MAX, scale); | |||
| } | |||
| static int replaygain_export(AVStream *st, | |||
| const uint8_t *track_gain, const uint8_t *track_peak, | |||
| const uint8_t *album_gain, const uint8_t *album_peak) | |||
| { | |||
| AVPacketSideData *sd, *tmp; | |||
| AVReplayGain *replaygain; | |||
| uint8_t *data; | |||
| int32_t tg, ag; | |||
| uint32_t tp, ap; | |||
| tg = parse_gain(track_gain); | |||
| ag = parse_gain(album_gain); | |||
| tp = parse_peak(track_peak); | |||
| ap = parse_peak(album_peak); | |||
| if (tg == INT32_MIN && ag == INT32_MIN) | |||
| return 0; | |||
| replaygain = av_mallocz(sizeof(*replaygain)); | |||
| if (!replaygain) | |||
| return AVERROR(ENOMEM); | |||
| tmp = av_realloc_array(st->side_data, st->nb_side_data + 1, sizeof(*tmp)); | |||
| if (!tmp) { | |||
| av_freep(&replaygain); | |||
| return AVERROR(ENOMEM); | |||
| } | |||
| st->side_data = tmp; | |||
| st->nb_side_data++; | |||
| sd = &st->side_data[st->nb_side_data - 1]; | |||
| sd->type = AV_PKT_DATA_REPLAYGAIN; | |||
| sd->data = (uint8_t*)replaygain; | |||
| sd->size = sizeof(*replaygain); | |||
| replaygain->track_gain = tg; | |||
| replaygain->track_peak = tp; | |||
| replaygain->album_gain = ag; | |||
| replaygain->album_peak = ap; | |||
| return 0; | |||
| } | |||
| int ff_replaygain_export(AVStream *st, AVDictionary *metadata) | |||
| { | |||
| const AVDictionaryEntry *tg, *tp, *ag, *ap; | |||
| tg = av_dict_get(metadata, "REPLAYGAIN_TRACK_GAIN", NULL, 0); | |||
| tp = av_dict_get(metadata, "REPLAYGAIN_TRACK_PEAK", NULL, 0); | |||
| ag = av_dict_get(metadata, "REPLAYGAIN_ALBUM_GAIN", NULL, 0); | |||
| ap = av_dict_get(metadata, "REPLAYGAIN_ALBUM_PEAK", NULL, 0); | |||
| return replaygain_export(st, | |||
| tg ? tg->value : NULL, | |||
| tp ? tp->value : NULL, | |||
| ag ? ag->value : NULL, | |||
| ap ? ap->value : NULL); | |||
| } | |||
| @@ -0,0 +1,31 @@ | |||
| /* | |||
| * This file is part of FFmpeg. | |||
| * | |||
| * FFmpeg is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation; either | |||
| * version 2.1 of the License, or (at your option) any later version. | |||
| * | |||
| * FFmpeg is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| * Lesser General Public License for more details. | |||
| * | |||
| * You should have received a copy of the GNU Lesser General Public | |||
| * License along with FFmpeg; if not, write to the Free Software | |||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| #ifndef AVFORMAT_REPLAYGAIN_H | |||
| #define AVFORMAT_REPLAYGAIN_H | |||
| #include "libavutil/dict.h" | |||
| #include "avformat.h" | |||
| /** | |||
| * Parse replaygain tags and export them as per-stream side data. | |||
| */ | |||
| int ff_replaygain_export(AVStream *st, AVDictionary *metadata); | |||
| #endif /* AVFORMAT_REPLAYGAIN_H */ | |||
| @@ -44,6 +44,7 @@ HEADERS = adler32.h \ | |||
| pixdesc.h \ | |||
| pixfmt.h \ | |||
| random_seed.h \ | |||
| replaygain.h \ | |||
| rational.h \ | |||
| ripemd.h \ | |||
| samplefmt.h \ | |||
| @@ -92,6 +92,10 @@ enum AVFrameSideDataType { | |||
| * The data is the AVDownmixInfo struct defined in libavutil/downmix_info.h. | |||
| */ | |||
| AV_FRAME_DATA_DOWNMIX_INFO, | |||
| /** | |||
| * ReplayGain information in the form of the AVReplayGain struct. | |||
| */ | |||
| AV_FRAME_DATA_REPLAYGAIN, | |||
| }; | |||
| typedef struct AVFrameSideData { | |||
| @@ -0,0 +1,51 @@ | |||
| /* | |||
| * | |||
| * This file is part of FFmpeg. | |||
| * | |||
| * FFmpeg is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation; either | |||
| * version 2.1 of the License, or (at your option) any later version. | |||
| * | |||
| * FFmpeg is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| * Lesser General Public License for more details. | |||
| * | |||
| * You should have received a copy of the GNU Lesser General Public | |||
| * License along with FFmpeg; if not, write to the Free Software | |||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| #ifndef AVUTIL_REPLAYGAIN_H | |||
| #define AVUTIL_REPLAYGAIN_H | |||
| #include <stdint.h> | |||
| /** | |||
| * ReplayGain information (see | |||
| * http://wiki.hydrogenaudio.org/index.php?title=ReplayGain_1.0_specification). | |||
| * The size of this struct is a part of the public ABI. | |||
| */ | |||
| typedef struct AVReplayGain { | |||
| /** | |||
| * Track replay gain in microbels (divide by 100000 to get the value in dB). | |||
| * Should be set to INT32_MIN when unknown. | |||
| */ | |||
| int32_t track_gain; | |||
| /** | |||
| * Peak track amplitude, with UINT32_MAX representing full scale. 0 when | |||
| * unknown. | |||
| */ | |||
| uint32_t track_peak; | |||
| /** | |||
| * Same as track_gain, but for the whole album. | |||
| */ | |||
| int32_t album_gain; | |||
| /** | |||
| * Same as track_peak, but for the whole album, | |||
| */ | |||
| uint32_t album_peak; | |||
| } AVReplayGain; | |||
| #endif /* AVUTIL_REPLAYGAIN_H */ | |||
| @@ -56,7 +56,7 @@ | |||
| */ | |||
| #define LIBAVUTIL_VERSION_MAJOR 52 | |||
| #define LIBAVUTIL_VERSION_MINOR 67 | |||
| #define LIBAVUTIL_VERSION_MINOR 68 | |||
| #define LIBAVUTIL_VERSION_MICRO 100 | |||
| #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ | |||