From 5539b3a9f6195fed91cbf10d4ecb2b7e6c75ac99 Mon Sep 17 00:00:00 2001
From: Carl Eugen Hoyos <ceffmpeg@gmail.com>
Date: Sun, 1 Oct 2017 18:13:14 +0200
Subject: [PATCH] lavf/amr: Add amrnb and amrwb demuxers.

Fixes ticket #6678.
---
 libavformat/Makefile     |    2 ++
 libavformat/allformats.c |    2 ++
 libavformat/amr.c        |   10 ++-----
 libavformat/amr.h        |   34 +++++++++++++++++++++
 libavformat/amrnb.c      |   73 ++++++++++++++++++++++++++++++++++++++++++++++
 libavformat/amrwb.c      |   73 ++++++++++++++++++++++++++++++++++++++++++++++
 libavformat/version.h    |    4 +--
 7 files changed, 189 insertions(+), 9 deletions(-)
 create mode 100644 libavformat/amr.h
 create mode 100644 libavformat/amrnb.c
 create mode 100644 libavformat/amrwb.c

diff --git a/libavformat/Makefile b/libavformat/Makefile
index df709c29..bf8fb86 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -87,6 +87,8 @@ OBJS-$(CONFIG_AIFF_MUXER)                += aiffenc.o id3v2enc.o
 OBJS-$(CONFIG_AIX_DEMUXER)               += aixdec.o
 OBJS-$(CONFIG_AMR_DEMUXER)               += amr.o
 OBJS-$(CONFIG_AMR_MUXER)                 += amr.o
+OBJS-$(CONFIG_AMRNB_DEMUXER)             += amrnb.o
+OBJS-$(CONFIG_AMRWB_DEMUXER)             += amrwb.o
 OBJS-$(CONFIG_ANM_DEMUXER)               += anm.o
 OBJS-$(CONFIG_APC_DEMUXER)               += apc.o
 OBJS-$(CONFIG_APE_DEMUXER)               += ape.o apetag.o img2.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index 405ddb5..dc8984e 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -63,6 +63,8 @@ static void register_all(void)
     REGISTER_MUXDEMUX(AIFF,             aiff);
     REGISTER_DEMUXER (AIX,              aix);
     REGISTER_MUXDEMUX(AMR,              amr);
+    REGISTER_DEMUXER (AMRNB,            amrnb);
+    REGISTER_DEMUXER (AMRWB,            amrwb);
     REGISTER_DEMUXER (ANM,              anm);
     REGISTER_DEMUXER (APC,              apc);
     REGISTER_DEMUXER (APE,              ape);
diff --git a/libavformat/amr.c b/libavformat/amr.c
index b5194a2..40653ce 100644
--- a/libavformat/amr.c
+++ b/libavformat/amr.c
@@ -29,11 +29,7 @@ Only mono files are supported.
 #include "libavutil/channel_layout.h"
 #include "avformat.h"
 #include "internal.h"
-
-typedef struct {
-    uint64_t cumulated_size;
-    uint64_t block_count;
-} AMRContext;
+#include "amr.h"
 
 static const char AMR_header[]   = "#!AMR\n";
 static const char AMRWB_header[] = "#!AMR-WB\n";
@@ -110,7 +106,7 @@ static int amr_read_header(AVFormatContext *s)
     return 0;
 }
 
-static int amr_read_packet(AVFormatContext *s, AVPacket *pkt)
+int ff_amr_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
     AVCodecParameters *par = s->streams[0]->codecpar;
     int read, size = 0, toc, mode;
@@ -171,7 +167,7 @@ AVInputFormat ff_amr_demuxer = {
     .priv_data_size = sizeof(AMRContext),
     .read_probe     = amr_probe,
     .read_header    = amr_read_header,
-    .read_packet    = amr_read_packet,
+    .read_packet    = ff_amr_read_packet,
     .flags          = AVFMT_GENERIC_INDEX,
 };
 #endif
diff --git a/libavformat/amr.h b/libavformat/amr.h
new file mode 100644
index 0000000..5c3760e
--- /dev/null
+++ b/libavformat/amr.h
@@ -0,0 +1,34 @@
+/*
+ * amr file format
+ * Copyright (c) 2001 FFmpeg project
+ *
+ * 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_AMR_H
+#define AVFORMAT_AMR_H
+
+#include "avformat.h"
+
+typedef struct {
+    uint64_t cumulated_size;
+    uint64_t block_count;
+} AMRContext;
+
+int ff_amr_read_packet(AVFormatContext *s, AVPacket *pkt);
+
+#endif
diff --git a/libavformat/amrnb.c b/libavformat/amrnb.c
new file mode 100644
index 0000000..cdfe976
--- /dev/null
+++ b/libavformat/amrnb.c
@@ -0,0 +1,73 @@
+/*
+ * amr-nb file format
+ * Copyright (c) 2017 Carl Eugen Hoyos
+ *
+ * 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
+ */
+
+#include "avformat.h"
+#include "amr.h"
+#include "internal.h"
+#include "libavutil/internal.h"
+#include "libavcodec/amrnbdata.h"
+
+static int amrnb_read_header(AVFormatContext *s)
+{
+    AVStream *st = avformat_new_stream(s, NULL);
+    if (!st)
+        return AVERROR(ENOMEM);
+    st->codecpar->codec_tag      = MKTAG('s', 'a', 'm', 'r');
+    st->codecpar->codec_id       = AV_CODEC_ID_AMR_NB;
+    st->codecpar->sample_rate    = 8000;
+    st->codecpar->channels       = 1;
+    st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+    st->codecpar->codec_type     = AVMEDIA_TYPE_AUDIO;
+    avpriv_set_pts_info(st, 64, 1, 8000);
+
+    return 0;
+}
+
+static int amrnb_probe(AVProbeData *p)
+{
+    int i, valid = 0;
+    const uint8_t *b = p->buf;
+    enum Mode mode;
+
+    while (i < p->buf_size) {
+        mode = b[i] >> 3 & 0x0F;
+        if (mode < N_MODES && (b[i] & 0x4) == 0x4) {
+            i += frame_sizes_nb[mode] + 1;
+            valid++;
+        } else {
+            valid = 0;
+            i++;
+        }
+    }
+    if (valid > 100)
+        return AVPROBE_SCORE_EXTENSION / 2 + 1;
+    return 0;
+}
+
+AVInputFormat ff_amrnb_demuxer = {
+    .name           = "amrnb",
+    .long_name      = NULL_IF_CONFIG_SMALL("raw AMR-NB"),
+    .priv_data_size = sizeof(AMRContext),
+    .read_probe     = amrnb_probe,
+    .read_header    = amrnb_read_header,
+    .read_packet    = ff_amr_read_packet,
+    .flags          = AVFMT_GENERIC_INDEX,
+};
diff --git a/libavformat/amrwb.c b/libavformat/amrwb.c
new file mode 100644
index 0000000..2aa631b
--- /dev/null
+++ b/libavformat/amrwb.c
@@ -0,0 +1,73 @@
+/*
+ * amr-wb file format
+ * Copyright (c) 2017 Carl Eugen Hoyos
+ *
+ * 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
+ */
+
+#include "avformat.h"
+#include "amr.h"
+#include "internal.h"
+#include "libavutil/internal.h"
+#include "libavcodec/amrwbdata.h"
+
+static int amrwb_probe(AVProbeData *p)
+{
+    int i, valid = 0;
+    const uint8_t *b = p->buf;
+    enum Mode mode;
+
+    while (i < p->buf_size) {
+        mode = b[i] >> 3 & 0x0F;
+        if (mode <= MODE_SID && (b[i] & 0x4) == 0x4) {
+            i += ((cf_sizes_wb[mode] + 7) >> 3) + 1;
+            valid++;
+        } else {
+            valid = 0;
+            i++;
+        }
+    }
+    if (valid > 100)
+        return AVPROBE_SCORE_EXTENSION / 2 + 1;
+    return 0;
+}
+
+static int amrwb_read_header(AVFormatContext *s)
+{
+    AVStream *st = avformat_new_stream(s, NULL);
+    if (!st)
+        return AVERROR(ENOMEM);
+    st->codecpar->codec_tag      = MKTAG('s', 'a', 'w', 'b');
+    st->codecpar->codec_id       = AV_CODEC_ID_AMR_WB;
+    st->codecpar->sample_rate    = 16000;
+    st->codecpar->channels       = 1;
+    st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+    st->codecpar->codec_type     = AVMEDIA_TYPE_AUDIO;
+    avpriv_set_pts_info(st, 64, 1, 16000);
+
+    return 0;
+}
+
+AVInputFormat ff_amrwb_demuxer = {
+    .name           = "amrwb",
+    .long_name      = NULL_IF_CONFIG_SMALL("raw AMR-WB"),
+    .priv_data_size = sizeof(AMRContext),
+    .read_probe     = amrwb_probe,
+    .read_header    = amrwb_read_header,
+    .read_packet    = ff_amr_read_packet,
+    .flags          = AVFMT_GENERIC_INDEX,
+};
diff --git a/libavformat/version.h b/libavformat/version.h
index ac6edf7..878917d 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -32,8 +32,8 @@
 // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium)
 // Also please add any ticket numbers that you believe might be affected here
 #define LIBAVFORMAT_VERSION_MAJOR  57
-#define LIBAVFORMAT_VERSION_MINOR  82
-#define LIBAVFORMAT_VERSION_MICRO 102
+#define LIBAVFORMAT_VERSION_MINOR  83
+#define LIBAVFORMAT_VERSION_MICRO 100
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
                                                LIBAVFORMAT_VERSION_MINOR, \
-- 
1.7.10.4

