diff mbox

[FFmpeg-devel] lavf/amr: Add amrnb and amrwb demuxers

Message ID CAB0OVGozKe45mYo2OTBiywmz__vvaps+edLCr0syzx_2Ohai=g@mail.gmail.com
State Superseded
Headers show

Commit Message

Carl Eugen Hoyos Oct. 7, 2017, 2:51 p.m. UTC
2017-10-01 18:23 GMT+02:00 Carl Eugen Hoyos <ceffmpeg@gmail.com>:
> 2017-09-27 18:08 GMT+02:00 Carl Eugen Hoyos <ceffmpeg@gmail.com>:
>
>> The existing amr demuxer does not allow reading streams,
>> it requires the 3GPP-conforming file header.
>> Attached patch allows reading amrnb and amrwb from (live)
>> streams, fixes ticket #6678.
>
> New patch with auto-detection attached, passes probecheck.

Simplified patch attached that does not duplicate two small arrays
in the object file that are already duplicated in the source code.
The uninitialized variable is also fixed.

I intend to apply soon, Carl Eugen
diff mbox

Patch

From 0f6592b1b7e3d01dd5c853b3269c4d47d49fed9f Mon Sep 17 00:00:00 2001
From: Carl Eugen Hoyos <ceffmpeg@gmail.com>
Date: Sat, 7 Oct 2017 16:50:55 +0200
Subject: [PATCH] lavf/amr: Add amrnb and amrwb demuxers.

Fixes ticket #6678.
---
 libavformat/Makefile     |    2 +
 libavformat/allformats.c |    2 +
 libavformat/amr.c        |  116 ++++++++++++++++++++++++++++++++++++++++++----
 libavformat/version.h    |    4 +-
 4 files changed, 112 insertions(+), 12 deletions(-)

diff --git a/libavformat/Makefile b/libavformat/Makefile
index df709c29..c4c8713 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)             += amr.o
+OBJS-$(CONFIG_AMRWB_DEMUXER)             += amr.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..da2e28b 100644
--- a/libavformat/amr.c
+++ b/libavformat/amr.c
@@ -38,6 +38,14 @@  typedef struct {
 static const char AMR_header[]   = "#!AMR\n";
 static const char AMRWB_header[] = "#!AMR-WB\n";
 
+static const uint8_t amrnb_packed_size[16] = {
+    13, 14, 16, 18, 20, 21, 27, 32, 6, 1, 1, 1, 1, 1, 1, 1
+};
+static const uint8_t amrwb_packed_size[16] = {
+    18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 1, 1, 1, 1, 1, 1
+};
+
+
 #if CONFIG_AMR_MUXER
 static int amr_write_header(AVFormatContext *s)
 {
@@ -126,17 +134,9 @@  static int amr_read_packet(AVFormatContext *s, AVPacket *pkt)
     mode = (toc >> 3) & 0x0F;
 
     if (par->codec_id == AV_CODEC_ID_AMR_NB) {
-        static const uint8_t packed_size[16] = {
-            12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0
-        };
-
-        size = packed_size[mode] + 1;
+        size = amrnb_packed_size[mode];
     } else if (par->codec_id == AV_CODEC_ID_AMR_WB) {
-        static const uint8_t packed_size[16] = {
-            18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 6, 0, 0, 0, 1, 1
-        };
-
-        size = packed_size[mode];
+        size = amrwb_packed_size[mode];
     }
 
     if (!size || av_new_packet(pkt, size))
@@ -176,6 +176,102 @@  AVInputFormat ff_amr_demuxer = {
 };
 #endif
 
+#if CONFIG_AMRNB_DEMUXER
+static int amrnb_probe(AVProbeData *p)
+{
+    int mode, i = 0, valid = 0;
+    const uint8_t *b = p->buf;
+
+    while (i < p->buf_size) {
+        mode = b[i] >> 3 & 0x0F;
+        if (mode < 9 && (b[i] & 0x4) == 0x4) {
+            i += amrnb_packed_size[mode];
+            valid++;
+        } else {
+                valid = 0;
+            i++;
+        }
+    }
+    if (valid > 100)
+        return AVPROBE_SCORE_EXTENSION / 2 + 1;
+    return 0;
+}
+
+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;
+}
+
+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    = amr_read_packet,
+    .flags          = AVFMT_GENERIC_INDEX,
+};
+#endif
+
+#if CONFIG_AMRWB_DEMUXER
+static int amrwb_probe(AVProbeData *p)
+{
+    int mode, i = 0, valid = 0;
+    const uint8_t *b = p->buf;
+
+    while (i < p->buf_size) {
+        mode = b[i] >> 3 & 0x0F;
+        if (mode < 10 && (b[i] & 0x4) == 0x4) {
+            i += amrwb_packed_size[mode];
+            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    = amr_read_packet,
+    .flags          = AVFMT_GENERIC_INDEX,
+};
+#endif
+
 #if CONFIG_AMR_MUXER
 AVOutputFormat ff_amr_muxer = {
     .name              = "amr",
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