From patchwork Mon Aug 24 23:28:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 21892 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id CBFBF4488E5 for ; Tue, 25 Aug 2020 02:34:59 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id AE5E3689C71; Tue, 25 Aug 2020 02:34:59 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f68.google.com (mail-wm1-f68.google.com [209.85.128.68]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 8C1F56802DE for ; Tue, 25 Aug 2020 02:34:53 +0300 (EEST) Received: by mail-wm1-f68.google.com with SMTP id z9so490979wmk.1 for ; Mon, 24 Aug 2020 16:34:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id; bh=MM2vCfOCNsHK4pdzXkJ2/KyNmAZKXQGZDL5KGG5t1KI=; b=jKxvC1Qvz9/BdCMo6WZ48WeWw1HQ+JVqQ6POxsNTHAm0DvmV6cRf+Z9BQoxGLu6FtV Oqtuin7g9kR3EWcvYHlfzUXh5kp+HTykjGU7/22GtrqnmK+9/UtQ+fufYnN59NoN0mIu vTxqtFyplyZ7sllnHQiMWWFmfdo3SHi+HsGk22B+0ivPBeczay1iwBuZpGyz9708Pjqj ebBm4Xlf4+8YjCQFUEvbLkIDW9wfC1p7B23AElLCPQ1o4QqhkJXExt9J7EUjqRzjFtBo m7IBuWNYIayXSCMxwnsBOge40EQHYVkvAA9txUGc54ZL+JFuTQPwklV1KdKb3FzizLr/ NC0A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=MM2vCfOCNsHK4pdzXkJ2/KyNmAZKXQGZDL5KGG5t1KI=; b=WR1qYUkGSodl02J/vAhsOPEMqRLuzD3oJZE8hIQiFGvgRUwltIHj5dlpEdWXJNA2zF TZUu5lNL0laM/skb3SUp1B4Ib6ArfIDUlmHF3YTIy+77lFqd6PJC9uAU6mDzKHd2fzn1 stYoZJEVpwdNLOFspaiOZEepoO8O4Zb0hXQq5TH/7fMzul+Acrbs8u4c9Ny7ayUT4jwh mS5M9UUCVtAk/fr+zumH8w6gA4uCCbpmbkTROaXI87Gi8nK1obCkjj3li+M9q+BwPuSq BRu6N56OBlV0co3bx6pYOvA9u94UWVurxcrBYwxL7EyUHOpntxNfWABCHgJwgpqOLSQc aVBg== X-Gm-Message-State: AOAM531TNPlcV3cGE9aNhzIpt3xD3Xt+4Ss39+2eHV+QYqgwzBWKWSfP /UIyw+IzyKBS880h0YJ37bSdIbomM7M= X-Google-Smtp-Source: ABdhPJzt421h6HZWcK75Fo1csI3FUHVyeREO4XY+dTudEknNVRyS7OLKJbPbDTppuxLXzKFywD7OKQ== X-Received: by 2002:a7b:c0c5:: with SMTP id s5mr1518934wmh.144.1598311748552; Mon, 24 Aug 2020 16:29:08 -0700 (PDT) Received: from localhost.localdomain ([94.250.163.64]) by smtp.gmail.com with ESMTPSA id c10sm23204139wrn.24.2020.08.24.16.29.07 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Aug 2020 16:29:08 -0700 (PDT) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Tue, 25 Aug 2020 01:28:56 +0200 Message-Id: <20200824232858.18938-1-onemda@gmail.com> X-Mailer: git-send-email 2.17.1 Subject: [FFmpeg-devel] [PATCH 1/3] avformat: add moflex demuxer X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Paul B Mahol --- [WIP] Missing video decoder. --- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/moflex.c | 291 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 293 insertions(+) create mode 100644 libavformat/moflex.c diff --git a/libavformat/Makefile b/libavformat/Makefile index cbb33fe37c..1e0ac317e5 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -319,6 +319,7 @@ OBJS-$(CONFIG_MLV_DEMUXER) += mlvdec.o riffdec.o OBJS-$(CONFIG_MM_DEMUXER) += mm.o OBJS-$(CONFIG_MMF_DEMUXER) += mmf.o OBJS-$(CONFIG_MMF_MUXER) += mmf.o rawenc.o +OBJS-$(CONFIG_MOFLEX_DEMUXER) += moflex.o OBJS-$(CONFIG_MOV_DEMUXER) += mov.o mov_chan.o mov_esds.o replaygain.o OBJS-$(CONFIG_MOV_MUXER) += movenc.o av1.o avc.o hevc.o vpcc.o \ movenchint.o mov_chan.o rtp.o \ diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 0aa9dd7198..28331facb9 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -249,6 +249,7 @@ extern AVInputFormat ff_mlv_demuxer; extern AVInputFormat ff_mm_demuxer; extern AVInputFormat ff_mmf_demuxer; extern AVOutputFormat ff_mmf_muxer; +extern AVInputFormat ff_moflex_demuxer; extern AVInputFormat ff_mov_demuxer; extern AVOutputFormat ff_mov_muxer; extern AVOutputFormat ff_mp2_muxer; diff --git a/libavformat/moflex.c b/libavformat/moflex.c new file mode 100644 index 0000000000..b3728b0e49 --- /dev/null +++ b/libavformat/moflex.c @@ -0,0 +1,291 @@ +/* + * MOFLEX demuxer + * Copyright (c) 2020 Paul B Mahol + * + * 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 "internal.h" + +typedef struct BitReader { + unsigned last; + unsigned pos; +} BitReader; + +typedef struct MOFLEXDemuxContext { + unsigned size; + int64_t pos; + int64_t ts; + int flags; + int in_block; + + BitReader br; +} MOFLEXDemuxContext; + +static int pop(BitReader *br, AVIOContext *pb) +{ + if (avio_feof(pb)) + return AVERROR_EOF; + + if ((br->pos & 7) == 0) + br->last = (unsigned)avio_r8(pb) << 24U; + else + br->last <<= 1; + + br->pos++; + return !!(br->last & 0x80000000); +} + +static int pop_int(BitReader *br, AVIOContext *pb, int n) +{ + int value = 0; + + for (int i = 0; i < n; i++) { + int ret = pop(br, pb); + + if (ret < 0) + return ret; + value = 2 * value + ret; + } + + return value; +} + +static int pop_length(BitReader *br, AVIOContext *pb) +{ + int n = 1; + + while (!pop(br, pb)) + n++; + + return n; +} + +static int read_var_byte(AVFormatContext *s, unsigned *out) +{ + AVIOContext *pb = s->pb; + unsigned value = 0, data; + + data = avio_r8(pb); + if (!(data & 0x80)) { + *out = data; + return 0; + } + + value = (data & 0x7F) << 7; + data = avio_r8(pb); + if (!(data & 0x80)) { + value |= data; + *out = value; + return 0; + } + + value = ((data & 0x7F) | value) << 7; + data = avio_r8(pb); + if (!(data & 0x80)) { + value |= data; + *out = value; + return 0; + } + + value = (((data & 0x7F) | value) << 7) | avio_r8(pb); + *out = value; + + return 0; +} + +static int moflex_probe(const AVProbeData *p) +{ + if (p->buf[0] != 0x4C && p->buf[1] != 0x32) + return 0; + + return AVPROBE_SCORE_MAX / 3; +} + +static int moflex_read_sync(AVFormatContext *s) +{ + MOFLEXDemuxContext *m = s->priv_data; + AVIOContext *pb = s->pb; + unsigned v10; + + if (avio_rb16(pb) != 0x4C32) { + avio_seek(pb, -2, SEEK_CUR); + return 1; + } + + v10 = avio_rb16(pb); + m->ts = avio_rb64(pb); + m->size = avio_rb16(pb) + 1; + + while (!avio_feof(pb)) { + unsigned type, ssize, codec_id = 0; + unsigned codec_type, width = 0, height = 0, sample_rate = 0, channels = 0; + int stream_index = -1; + int format; + AVRational fps; + + read_var_byte(s, &type); + read_var_byte(s, &ssize); + + switch (type) { + case 0: + if (ssize > 0) + avio_skip(pb, ssize); + return 0; + case 2: + codec_type = AVMEDIA_TYPE_AUDIO; + stream_index = avio_r8(pb); + codec_id = avio_r8(pb); + switch (codec_id) { + case 0: codec_id = AV_CODEC_ID_FASTAUDIO; break; + case 1: codec_id = AV_CODEC_ID_ADPCM_IMA_MOFLEX; break; + } + sample_rate = avio_rb24(pb) + 1; + channels = avio_r8(pb) + 1; + break; + case 1: + case 3: + codec_type = AVMEDIA_TYPE_VIDEO; + stream_index = avio_r8(pb); + codec_id = avio_r8(pb); + fps.num = avio_rb16(pb); + fps.den = avio_rb16(pb); + width = avio_rb16(pb); + height = avio_rb16(pb); + format = AV_PIX_FMT_YUV420P; + avio_skip(pb, type == 3 ? 3 : 2); + break; + case 4: + codec_type = AVMEDIA_TYPE_DATA; + stream_index = avio_r8(pb); + avio_skip(pb, 1); + break; + } + + if (stream_index == s->nb_streams) { + AVStream *st = avformat_new_stream(s, NULL); + + st->codecpar->codec_type = codec_type; + st->codecpar->codec_id = codec_id; + st->codecpar->width = width; + st->codecpar->height = height; + st->codecpar->sample_rate= sample_rate; + st->codecpar->channels = channels; + st->codecpar->format = format; + st->priv_data = av_packet_alloc(); + if (!st->priv_data) + return AVERROR(ENOMEM); + + if (sample_rate) + avpriv_set_pts_info(st, 63, 1, sample_rate); + else + avpriv_set_pts_info(st, 63, fps.den, fps.num); + } + } + + return 0; +} + +static int moflex_read_header(AVFormatContext *s) +{ + int ret; + + ret = moflex_read_sync(s); + if (ret < 0) + return ret; + + avio_seek(s->pb, 0, SEEK_SET); + + return 0; +} + +static int moflex_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + MOFLEXDemuxContext *m = s->priv_data; + AVIOContext *pb = s->pb; + BitReader *br = &m->br; + int ret; + + while (!avio_feof(pb)) { + if (!m->in_block) { + m->pos = avio_tell(pb); + + ret = moflex_read_sync(s); + if (ret < 0) + return ret; + + m->flags = avio_r8(pb); + if (m->flags & 2) + avio_skip(pb, 2); + } + + while ((avio_tell(pb) < m->pos + m->size) && !avio_feof(pb) && avio_r8(pb)) { + int stream_index, pkt_size, endframe; + AVPacket *packet; + + m->in_block = 1; + + avio_seek(pb, -1, SEEK_CUR); + br->pos = br->last = 0; + + stream_index = pop_int(br, pb, pop_length(br, pb)); + if (stream_index < 0) + return stream_index; + if (stream_index >= s->nb_streams) + return AVERROR_INVALIDDATA; + + endframe = pop(br, pb); + if (endframe < 0) + return endframe; + if (endframe) { + pop_int(br, pb, pop_length(br, pb)); + pop(br, pb); + pop_int(br, pb, pop_length(br, pb) * 2 + 26); + } + + pkt_size = pop_int(br, pb, 13) + 1; + packet = s->streams[stream_index]->priv_data; + + ret = av_append_packet(pb, packet, pkt_size); + if (endframe) { + av_packet_move_ref(pkt, packet); + pkt->pos = m->pos; + pkt->stream_index = stream_index; + return ret; + } + } + + m->in_block = 0; + + if (m->flags % 2 == 0) + avio_seek(pb, m->pos + m->size, SEEK_SET); + } + + return AVERROR_EOF; +} + +AVInputFormat ff_moflex_demuxer = { + .name = "moflex", + .long_name = NULL_IF_CONFIG_SMALL("MobiClip MOFLEX"), + .priv_data_size = sizeof(MOFLEXDemuxContext), + .read_probe = moflex_probe, + .read_header = moflex_read_header, + .read_packet = moflex_read_packet, + .extensions = "moflex", + .flags = AVFMT_GENERIC_INDEX, +}; From patchwork Mon Aug 24 23:28:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 21891 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id C854D4488E5 for ; Tue, 25 Aug 2020 02:34:47 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id AC85068A71D; Tue, 25 Aug 2020 02:34:47 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f52.google.com (mail-wm1-f52.google.com [209.85.128.52]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id E1DDB68A48B for ; Tue, 25 Aug 2020 02:34:40 +0300 (EEST) Received: by mail-wm1-f52.google.com with SMTP id 83so581434wme.4 for ; Mon, 24 Aug 2020 16:34:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references; bh=pvkN4Sd/AyAQ+mOR/qStKf4N66oA3uKX0OdXgh80me4=; b=qE8qn2IaDUZrCI7EYxvhAHd1be+9woZXHUkV2ZPjxrsHPbS7LvzjjhOjpesTm+ZP8N WBplOVXP+tybAQDpLVgppxNu50onz+B+7eLX63y2gVx7ZGdFE9VRCFL7ovk1omEfNPEp S/n/WantTOGzzGiHgkWiTGi9dricv8t8TN4qyQHuh6JeLJU7JpV2bMXEaRYt52titxld yCJAEaKnHG/G1wv3VK3LN8p8lm1g8a2o7z1GD7eLLclUuHsU5taEaQrs/Hi9VmVzQ5YA mzl6nLfvt8kbZOfoNIYD51yfey9qcEMHzqZL/AAO//zjmV2pEjU0oqu3RFqanE7BL3YA bNGw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=pvkN4Sd/AyAQ+mOR/qStKf4N66oA3uKX0OdXgh80me4=; b=fGniW0AM19AqtkTi/vi8qB6bAg1TyGKGgu3yO0MzP7Ha/H9tSJ1ghGtxo6/Yvd1ioc GzNjRVUxcd8Zk/2hIrjJXQ8ciVPS5ZGh0xxLGkNW4eKG/BI+M92pSQmt0+ESh4RMNXOC ffWbb1LzVQR6ek71Zdx62ucHxnnF6fFrhsDuJ3BhbTus8Y4l9PVXRb1POXjcUC9iQefB vai5R8ojSGWXMaKjoo7V14fmKIk9wOyX8t5viexT9+FC8MIDqiTU3CeMboTzS750H2lO WTe0G8bW6U5m3kRUoB/P46TioLMjf3JMaBikueWKaMAoRVVC3qAE8ZeiBFh8orxYAiYG 9fjA== X-Gm-Message-State: AOAM532CVn62U4oZTj4jrZhg+pOgDKgm/RqJkE8W1VGqm7F+I4NgdZpP zDzKOD+f78EdIOcJtlNQWU5NUCPLKrs= X-Google-Smtp-Source: ABdhPJxYsi/JbOWj9rci6eYJivvvD8NBTT4H0u9/W5yqv0Ic3+0vQx99/5r/xUdFtQuAOr+Ore48CQ== X-Received: by 2002:a1c:ed16:: with SMTP id l22mr1368424wmh.80.1598311749565; Mon, 24 Aug 2020 16:29:09 -0700 (PDT) Received: from localhost.localdomain ([94.250.163.64]) by smtp.gmail.com with ESMTPSA id c10sm23204139wrn.24.2020.08.24.16.29.08 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Aug 2020 16:29:09 -0700 (PDT) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Tue, 25 Aug 2020 01:28:57 +0200 Message-Id: <20200824232858.18938-2-onemda@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200824232858.18938-1-onemda@gmail.com> References: <20200824232858.18938-1-onemda@gmail.com> Subject: [FFmpeg-devel] [PATCH 2/3] avcodec: add ADPCM IMA MOFLEX decoder X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Paul B Mahol --- libavcodec/Makefile | 1 + libavcodec/adpcm.c | 26 ++++++++++++++++++++++++++ libavcodec/allcodecs.c | 1 + libavcodec/codec_desc.c | 7 +++++++ libavcodec/codec_id.h | 1 + libavcodec/utils.c | 2 ++ 6 files changed, 38 insertions(+) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index ca2e8a2530..191c4e0a7c 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -866,6 +866,7 @@ OBJS-$(CONFIG_ADPCM_IMA_DK4_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_EA_EACS_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_EA_SEAD_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_ISS_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_MOFLEX_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_MTF_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_OKI_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_QT_DECODER) += adpcm.o adpcm_data.o diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c index 1366932352..71e37efde7 100644 --- a/libavcodec/adpcm.c +++ b/libavcodec/adpcm.c @@ -210,6 +210,7 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx) case AV_CODEC_ID_ADPCM_PSX: case AV_CODEC_ID_ADPCM_MTAF: case AV_CODEC_ID_ADPCM_ARGO: + case AV_CODEC_ID_ADPCM_IMA_MOFLEX: avctx->sample_fmt = AV_SAMPLE_FMT_S16P; break; case AV_CODEC_ID_ADPCM_IMA_WS: @@ -774,6 +775,7 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb, case AV_CODEC_ID_ADPCM_4XM: case AV_CODEC_ID_ADPCM_AGM: case AV_CODEC_ID_ADPCM_IMA_DAT4: + case AV_CODEC_ID_ADPCM_IMA_MOFLEX: case AV_CODEC_ID_ADPCM_IMA_ISS: header_size = 4 * ch; break; case AV_CODEC_ID_ADPCM_IMA_AMV: header_size = 8; break; case AV_CODEC_ID_ADPCM_IMA_SMJPEG: header_size = 4 * ch; break; @@ -1298,6 +1300,29 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, *samples++ = adpcm_ima_expand_nibble(&c->status[st], v2, 3); } break; + case AV_CODEC_ID_ADPCM_IMA_MOFLEX: + for (channel = 0; channel < avctx->channels; channel++) { + cs = &c->status[channel]; + cs->step_index = sign_extend(bytestream2_get_le16u(&gb), 16); + cs->predictor = sign_extend(bytestream2_get_le16u(&gb), 16); + if (cs->step_index > 88u){ + av_log(avctx, AV_LOG_ERROR, "ERROR: step_index[%d] = %i\n", + channel, cs->step_index); + return AVERROR_INVALIDDATA; + } + } + + for (int subframe = 0; subframe < nb_samples / 256; subframe++) { + for (channel = 0; channel < avctx->channels; channel++) { + samples = samples_p[channel] + 256 * subframe; + for (n = 0; n < 256; n += 2) { + int v = bytestream2_get_byteu(&gb); + *samples++ = adpcm_ima_expand_nibble(&c->status[channel], v & 0x0F, 3); + *samples++ = adpcm_ima_expand_nibble(&c->status[channel], v >> 4 , 3); + } + } + } + break; case AV_CODEC_ID_ADPCM_IMA_DAT4: for (channel = 0; channel < avctx->channels; channel++) { cs = &c->status[channel]; @@ -2107,6 +2132,7 @@ ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_DK4, sample_fmts_s16, adpcm_ima_dk4, ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_EA_EACS, sample_fmts_s16, adpcm_ima_ea_eacs, "ADPCM IMA Electronic Arts EACS"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_EA_SEAD, sample_fmts_s16, adpcm_ima_ea_sead, "ADPCM IMA Electronic Arts SEAD"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_ISS, sample_fmts_s16, adpcm_ima_iss, "ADPCM IMA Funcom ISS"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_MOFLEX, sample_fmts_s16p, adpcm_ima_moflex, "ADPCM IMA MobiClip MOFLEX"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_MTF, sample_fmts_s16, adpcm_ima_mtf, "ADPCM IMA Capcom's MT Framework"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_OKI, sample_fmts_s16, adpcm_ima_oki, "ADPCM IMA Dialogic OKI"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_QT, sample_fmts_s16p, adpcm_ima_qt, "ADPCM IMA QuickTime"); diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 729d2fd9ad..084a289c9e 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -619,6 +619,7 @@ extern AVCodec ff_adpcm_ima_dk4_decoder; extern AVCodec ff_adpcm_ima_ea_eacs_decoder; extern AVCodec ff_adpcm_ima_ea_sead_decoder; extern AVCodec ff_adpcm_ima_iss_decoder; +extern AVCodec ff_adpcm_ima_moflex_decoder; extern AVCodec ff_adpcm_ima_mtf_decoder; extern AVCodec ff_adpcm_ima_oki_decoder; extern AVCodec ff_adpcm_ima_qt_encoder; diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 0ae6aee63b..b5bc5c3c71 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -2376,6 +2376,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Cunning Developments"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_ADPCM_IMA_MOFLEX, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ima_moflex", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA MobiClip MOFLEX"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, /* AMR */ { diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index 896ecb0ce0..aac1174f28 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -388,6 +388,7 @@ enum AVCodecID { AV_CODEC_ID_ADPCM_IMA_ALP, AV_CODEC_ID_ADPCM_IMA_MTF, AV_CODEC_ID_ADPCM_IMA_CUNNING, + AV_CODEC_ID_ADPCM_IMA_MOFLEX, /* AMR */ AV_CODEC_ID_AMR_NB = 0x12000, diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 14cb5cf1aa..187ce230b8 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -1664,6 +1664,8 @@ static int get_audio_frame_duration(enum AVCodecID id, int sr, int ch, int ba, if (ch > 0 && ch < INT_MAX/16) { /* calc from frame_bytes and channels */ switch (id) { + case AV_CODEC_ID_ADPCM_IMA_MOFLEX: + return (frame_bytes - 4 * ch) / (128 * ch) * 256; case AV_CODEC_ID_ADPCM_AFC: return frame_bytes / (9 * ch) * 16; case AV_CODEC_ID_ADPCM_PSX: From patchwork Mon Aug 24 23:28:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 21893 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 4353344A9F4 for ; Tue, 25 Aug 2020 03:00:23 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 23E9A689E2F; Tue, 25 Aug 2020 03:00:23 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr1-f67.google.com (mail-wr1-f67.google.com [209.85.221.67]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 990F6680C14 for ; Tue, 25 Aug 2020 03:00:17 +0300 (EEST) Received: by mail-wr1-f67.google.com with SMTP id b18so216283wrs.7 for ; Mon, 24 Aug 2020 17:00:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references; bh=GvcylmqEzFCQEJjpAfACKkL6P7bpbTYI9ca778KIETA=; b=DxdlJfaLqNCtTeL2dZgQRkQhKVUUC85gcb2ZIQo3EC9nh8Tco0/wviXS6PR58QEpnZ ExpFhP/6Ij0k0svFHfilT+VyIM73kh5e2fq0o1z9nwTY2wSbm9B9xs+RxDmPTsSA2AFs 5WgrWZWchENfKtDX988qfGapuukp3BJBo217FxubpLmtJ3WZZmxPFSEEnFyHJ71oTdTB Hu/AeM0XPxTxUtp1BQyijIKbKm6RiZMS4Kw+nI3E5reGnyX3E8ju2EjccrklxneokSvW PH2TmYOoSmWZ/C6aoC9rei2h2nAU1tsQF+VdNeK1vKUUxCpCs/1mUywdXZ4//hKHdu8v WW7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=GvcylmqEzFCQEJjpAfACKkL6P7bpbTYI9ca778KIETA=; b=POCPJ5UbTtXsWCRfxOYU/LjgbKI07Fe4j8XfLwnxf7qKS5iqpof54ZkAA5pZAUXuQZ a7ViG6NXHR7PovTtGb+2Snm/lLRpGiiMOpwUGWHWTE2KZTvHjV3r/B5ieeu8HN4iFQGn FfwOVfVycBAHVzqAK/nlKspWgRbOrpFRQ7XXXIMnj7LPyDQkwHKx63uf4VrcoqrWbW9M qfnreGtBUlg0jygOVCmpiTNZTSDuxzm9rxVVub9mf6DcWMlOt6KxJaBd0cMdjWl+rXzg 8b3/MbJ6Ve8owW/81xhVhYsMPrwndYHvNnQhPOF32W2lxBO/jsB9xF+qBSO6692fNl6Q A06w== X-Gm-Message-State: AOAM530/aleHzXrIWWcFHCnE5qTJD7Tf8CpSmGbfy5zOcgkY6Od6YKuQ nxi1MP+yJkfvMkBkX9PsUPQur1oMKG0= X-Google-Smtp-Source: ABdhPJxTH1oCTTiMGCXZ763mB1iO0vYU1oClqm1irP7+wYpX40T//ZrdwTFyy7PU1rszcYZ3hkcx4g== X-Received: by 2002:a5d:68ca:: with SMTP id p10mr8335601wrw.372.1598311750780; Mon, 24 Aug 2020 16:29:10 -0700 (PDT) Received: from localhost.localdomain ([94.250.163.64]) by smtp.gmail.com with ESMTPSA id c10sm23204139wrn.24.2020.08.24.16.29.09 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Aug 2020 16:29:10 -0700 (PDT) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Tue, 25 Aug 2020 01:28:58 +0200 Message-Id: <20200824232858.18938-3-onemda@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200824232858.18938-1-onemda@gmail.com> References: <20200824232858.18938-1-onemda@gmail.com> Subject: [FFmpeg-devel] [PATCH 3/3] avcodec: add FastAudio decoder X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Paul B Mahol --- libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/codec_desc.c | 7 ++ libavcodec/codec_id.h | 1 + libavcodec/fastaudio.c | 200 ++++++++++++++++++++++++++++++++++++++++ libavcodec/utils.c | 2 + 6 files changed, 212 insertions(+) create mode 100644 libavcodec/fastaudio.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 191c4e0a7c..6f75f26c84 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -317,6 +317,7 @@ OBJS-$(CONFIG_ESCAPE124_DECODER) += escape124.o OBJS-$(CONFIG_ESCAPE130_DECODER) += escape130.o OBJS-$(CONFIG_EVRC_DECODER) += evrcdec.o acelp_vectors.o lsp.o OBJS-$(CONFIG_EXR_DECODER) += exr.o exrdsp.o +OBJS-$(CONFIG_FASTAUDIO_DECODER) += fastaudio.o OBJS-$(CONFIG_FFV1_DECODER) += ffv1dec.o ffv1.o OBJS-$(CONFIG_FFV1_ENCODER) += ffv1enc.o ffv1.o OBJS-$(CONFIG_FFWAVESYNTH_DECODER) += ffwavesynth.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 084a289c9e..3920eb37ce 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -430,6 +430,7 @@ extern AVCodec ff_dst_decoder; extern AVCodec ff_eac3_encoder; extern AVCodec ff_eac3_decoder; extern AVCodec ff_evrc_decoder; +extern AVCodec ff_fastaudio_decoder; extern AVCodec ff_ffwavesynth_decoder; extern AVCodec ff_flac_encoder; extern AVCodec ff_flac_decoder; diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index b5bc5c3c71..9a3eaf7d98 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -3130,6 +3130,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("CRI HCA"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_FASTAUDIO, + .type = AVMEDIA_TYPE_AUDIO, + .name = "fastaudio", + .long_name = NULL_IF_CONFIG_SMALL("MobiClip FastAudio"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, /* subtitle codecs */ { diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index aac1174f28..aac7f63eb6 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -504,6 +504,7 @@ enum AVCodecID { AV_CODEC_ID_MPEGH_3D_AUDIO, AV_CODEC_ID_SIREN, AV_CODEC_ID_HCA, + AV_CODEC_ID_FASTAUDIO, /* subtitle codecs */ AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. diff --git a/libavcodec/fastaudio.c b/libavcodec/fastaudio.c new file mode 100644 index 0000000000..354336d17e --- /dev/null +++ b/libavcodec/fastaudio.c @@ -0,0 +1,200 @@ +/* + * MOFLEX Fast Audio decoder + * Copyright (c) 2020 Paul B Mahol + * + * 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 "libavutil/intreadwrite.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "mathops.h" + +typedef struct ChannelItems { + float f[8]; + float last; +} ChannelItems; + +typedef struct FastAudioContext { + float table[8][64]; + + ChannelItems *ch; +} FastAudioContext; + +static av_cold int fastaudio_init(AVCodecContext *avctx) +{ + FastAudioContext *s = avctx->priv_data; + + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + + for (int i = 0; i < 8; i++) + s->table[0][i] = (i - 159.5f) / 160.f; + for (int i = 0; i < 11; i++) + s->table[0][i + 8] = (i - 37.5f) / 40.f; + for (int i = 0; i < 27; i++) + s->table[0][i + 8 + 11] = (i - 13.f) / 20.f; + for (int i = 0; i < 11; i++) + s->table[0][i + 8 + 11 + 27] = (i + 27.5f) / 40.f; + for (int i = 0; i < 7; i++) + s->table[0][i + 8 + 11 + 27 + 11] = (i + 152.5f) / 160.f; + + memcpy(s->table[1], s->table[0], sizeof(s->table[0])); + + for (int i = 0; i < 7; i++) + s->table[2][i] = (i - 33.5f) / 40.f; + for (int i = 0; i < 25; i++) + s->table[2][i + 7] = (i - 13.f) / 20.f; + + for (int i = 0; i < 32; i++) + s->table[3][i] = -s->table[2][31 - i]; + + for (int i = 0; i < 16; i++) + s->table[4][i] = i * 0.22f / 3.f - 0.6f; + + for (int i = 0; i < 16; i++) + s->table[5][i] = i * 0.20f / 3.f - 0.3f; + + for (int i = 0; i < 8; i++) + s->table[6][i] = i * 0.36f / 3.f - 0.4f; + + for (int i = 0; i < 8; i++) + s->table[7][i] = i * 0.34f / 3.f - 0.2f; + + s->ch = av_calloc(avctx->channels, sizeof(*s->ch)); + if (!s->ch) + return AVERROR(ENOMEM); + + return 0; +} + +static int read_bits(int bits, int *ppos, unsigned *src) +{ + int r, pos; + + pos = *ppos; + pos += bits; + r = src[(pos - 1) / 32] >> (32 - pos % 32); + *ppos = pos; + + return r & ((1 << (bits % 32)) - 1); +} + +static const uint8_t bits[8] = { 6, 6, 5, 5, 4, 0, 3, 3, }; + +static void set_sample(int i, int j, int v, float *result, int *pads, float tblVal) +{ + result[i * 64 + pads[i] + j * 3] = tblVal * (2 * v - 7); +} + +static int fastaudio_decode(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *pkt) +{ + FastAudioContext *s = avctx->priv_data; + GetByteContext gb; + AVFrame *frame = data; + int subframes; + int ret; + + subframes = pkt->size / (40 * avctx->channels); + frame->nb_samples = subframes * 256; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + bytestream2_init(&gb, pkt->data, pkt->size); + + for (int subframe = 0; subframe < subframes; subframe++) { + for (int channel = 0; channel < avctx->channels; channel++) { + ChannelItems *ch = &s->ch[channel]; + float result[256] = { 0 }; + unsigned src[10]; + int inds[4], pads[4]; + float m[8]; + int pos = 0; + + for (int i = 0; i < 10; i++) + src[i] = bytestream2_get_le32(&gb); + + for (int i = 0; i < 8; i++) + m[7 - i] = s->table[i][read_bits(bits[i], &pos, src)]; + + for (int i = 0; i < 4; i++) + inds[3 - i] = read_bits(6, &pos, src); + + for (int i = 0; i < 4; i++) + pads[3 - i] = read_bits(2, &pos, src); + + for (int i = 0, index5 = 0; i < 4; i++) { + float tblVal = av_int2float((inds[i] + 1) << 20) * powf(2.f, 116.f); + + for (int j = 0, tmp = 0; j < 21; j++) { + set_sample(i, j, j == 20 ? tmp / 2 : read_bits(3, &pos, src), result, pads, tblVal); + if (j % 10 == 9) + tmp = 4 * tmp + read_bits(2, &pos, src); + if (j == 20) + index5 = 2 * index5 + tmp % 2; + } + + m[2] = s->table[5][index5]; + } + + for (int i = 0; i < 256; i++) { + float x = result[i]; + + for (int j = 0; j < 8; j++) { + x -= m[j] * ch->f[j]; + ch->f[j] += m[j] * x; + } + + memmove(&ch->f[0], &ch->f[1], sizeof(float) * 7); + ch->f[7] = x; + ch->last = x + ch->last * 0.86f; + result[i] = ch->last * 2.f; + } + + memcpy(frame->extended_data[channel] + 1024 * subframe, result, 256 * sizeof(float)); + } + } + + *got_frame = 1; + + return pkt->size; +} + +static av_cold int fastaudio_close(AVCodecContext *avctx) +{ + FastAudioContext *s = avctx->priv_data; + + av_freep(&s->ch); + + return 0; +} + +AVCodec ff_fastaudio_decoder = { + .name = "fastaudio", + .long_name = NULL_IF_CONFIG_SMALL("MobiClip FastAudio"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_FASTAUDIO, + .priv_data_size = sizeof(FastAudioContext), + .init = fastaudio_init, + .decode = fastaudio_decode, + .close = fastaudio_close, + .capabilities = AV_CODEC_CAP_DR1, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 187ce230b8..2e5185f364 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -1664,6 +1664,8 @@ static int get_audio_frame_duration(enum AVCodecID id, int sr, int ch, int ba, if (ch > 0 && ch < INT_MAX/16) { /* calc from frame_bytes and channels */ switch (id) { + case AV_CODEC_ID_FASTAUDIO: + return frame_bytes / (40 * ch) * 256; case AV_CODEC_ID_ADPCM_IMA_MOFLEX: return (frame_bytes - 4 * ch) / (128 * ch) * 256; case AV_CODEC_ID_ADPCM_AFC: