logo

English

FFMpeg에서 DOP (DSD-over-PCM) 구현 패치

by 엉뚱도마뱀 posted Dec 20, 2018
?

Shortcut

PrevPrev Article

NextNext Article

Larger Font Smaller Font Up Down Go comment Print
?

Shortcut

PrevPrev Article

NextNext Article

Larger Font Smaller Font Up Down Go comment Print
Signed-off-by: Peter Ross <pross at xvid.org>
---
 Changelog               |   1 +
 doc/general.texi        |   1 +
 libavcodec/Makefile     |   2 +
 libavcodec/allcodecs.c  |   1 +
 libavcodec/avcodec.h    |   1 +
 libavcodec/codec_desc.c |   7 ++
 libavcodec/dop.c        | 172 ++++++++++++++++++++++++++++++++++++++++++++++++
 libavcodec/utils.c      |   1 +
 8 files changed, 186 insertions(+)
 create mode 100644 libavcodec/dop.c

diff --git a/Changelog b/Changelog
index 8d61c9d..cbc30d0 100644
--- a/Changelog
+++ b/Changelog
@@ -22,6 +22,7 @@ version <next>:
 - On2 AVC (Audio for Video) decoder
 - support for decoding through DXVA2 in ffmpeg
 - libbs2b-based stereo-to-binaural audio filter
+- DoP (DSD-over-PCM)
 
 
 version 2.2:
diff --git a/doc/general.texi b/doc/general.texi
index 8a73cbf..99dc01c 100644
--- a/doc/general.texi
+++ b/doc/general.texi
@@ -891,6 +891,7 @@ following image formats are supported:
 @item COOK                   @tab     @tab  X
     @tab All versions except 5.1 are supported.
 @item DCA (DTS Coherent Acoustics)  @tab  X  @tab  X
+ at item DoP (DSD-over-PCM); signed 24-bit little-endian  @tab  X  @tab  X
 @item DPCM id RoQ            @tab  X  @tab  X
     @tab Used in Quake III, Jedi Knight 2 and other computer games.
 @item DPCM Interplay         @tab     @tab  X
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 7c475fb..433e438 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -177,6 +177,8 @@ OBJS-$(CONFIG_DIRAC_DECODER)           += diracdec.o dirac.o diracdsp.o \
 OBJS-$(CONFIG_DFA_DECODER)             += dfa.o
 OBJS-$(CONFIG_DNXHD_DECODER)           += dnxhddec.o dnxhddata.o
 OBJS-$(CONFIG_DNXHD_ENCODER)           += dnxhdenc.o dnxhddata.o
+OBJS-$(CONFIG_DOP_S24LE_DECODER)       += dop.o
+OBJS-$(CONFIG_DOP_S24LE_ENCODER)       += dop.o
 OBJS-$(CONFIG_DPX_DECODER)             += dpx.o
 OBJS-$(CONFIG_DPX_ENCODER)             += dpxenc.o
 OBJS-$(CONFIG_DSD_LSBF_DECODER)        += dsddec.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index eb6b0c3..c1bb3db 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -337,6 +337,7 @@ void avcodec_register_all(void)
     REGISTER_DECODER(BMV_AUDIO,         bmv_audio);
     REGISTER_DECODER(COOK,              cook);
     REGISTER_ENCDEC (DCA,               dca);
+    REGISTER_ENCDEC (DOP_S24LE,         dop_s24le);
     REGISTER_ENCDEC (DSD_LSBF,          dsd_lsbf);
     REGISTER_ENCDEC (DSD_MSBF,          dsd_msbf);
     REGISTER_ENCDEC (DSD_LSBF_PLANAR,   dsd_lsbf_planar);
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 94d4cf0..488a521 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -497,6 +497,7 @@ enum AVCodecID {
     AV_CODEC_ID_DSD_MSBF    = MKBETAG('D','S','D','M'),
     AV_CODEC_ID_DSD_LSBF_PLANAR = MKBETAG('D','S','D','1'),
     AV_CODEC_ID_DSD_MSBF_PLANAR = MKBETAG('D','S','D','8'),
+    AV_CODEC_ID_DOP_S24LE   = MKBETAG('D','O','P','L'),
 
     /* subtitle codecs */
     AV_CODEC_ID_FIRST_SUBTITLE = 0x17000,          ///< A dummy ID pointing at the start of subtitle codecs.
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 057c6a3..3b474f8 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -2508,6 +2508,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("DSD (Direct Stream Digital), most significant bit first, planar"),
         .props     = AV_CODEC_PROP_LOSSLESS,
     },
+    {
+        .id        = AV_CODEC_ID_DOP_S24LE,
+        .type      = AVMEDIA_TYPE_AUDIO,
+        .name      = "dop_s24le",
+        .long_name = NULL_IF_CONFIG_SMALL("DoP (DSD-over-PCM); signed 24-bit little-endian"),
+        .props     = AV_CODEC_PROP_LOSSLESS,
+    },
 
     /* subtitle codecs */
     {
diff --git a/libavcodec/dop.c b/libavcodec/dop.c
new file mode 100644
index 0000000..0c04add
--- /dev/null
+++ b/libavcodec/dop.c
@@ -0,0 +1,172 @@
+/*
+ * DSD-over-PCM (DOP) encoder and decoder
+ * Copyright (c) 2014 Peter Ross
+ *
+ * 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
+ * DSD-over-PCM (DOP) encoder and decoder
+ */
+
+#include "libavcodec/internal.h"
+#include "bytestream.h"
+#include "avcodec.h"
+
+typedef struct {
+    int state;
+    int sync;
+} DOPContext;
+
+static const uint8_t dop_marker[2] = {0x05, 0xFA};
+
+static av_cold int decode_init(AVCodecContext *avctx)
+{
+    DOPContext * s = avctx->priv_data;
+    avctx->sample_fmt = AV_SAMPLE_FMT_DSD;
+
+    switch(avctx->sample_rate) {
+    case 176400:
+    case 352800:
+       avctx->sample_rate *= 16;
+       break;
+    case 2822400:
+    case 5644800:
+       break;
+    default:
+       av_log(avctx, AV_LOG_WARNING, "unsupported sample rate\n");
+    }
+    s->sync = 32 * avctx->channels;
+    return 0;
+}
+
+static int decode_frame(AVCodecContext *avctx, void *data,
+                        int *got_frame_ptr, AVPacket *avpkt)
+{
+    DOPContext * s = avctx->priv_data;
+    const uint8_t *src = avpkt->data;
+    uint8_t *dst;
+    AVFrame *frame = data;
+    int ret, i, ch;
+    int pcm_samples = avpkt->size / (3 * avctx->channels);
+    frame->nb_samples = 2 * pcm_samples;
+    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
+        return ret;
+
+    dst = frame->data[0];
+
+    for (i = 0; i < pcm_samples; i++) {
+        for (ch = 0; ch < avctx->channels; ch++) {
+            uint8_t d1     = src[0];
+            uint8_t d0     = src[1];
+
+            uint8_t marker = src[2];
+            if (!s->sync) {
+                if (marker == 0x05 || marker == 0xFA) {
+                    s->state = marker == 0xFA;
+                    s->sync++;
+                }
+                d0 = d1 = 0x69;
+            } else {
+                if (marker != dop_marker[s->state]) { /* lost sync */
+                    s->sync = 0;
+                    d0 = d1 = 0x69;
+                } else if (s->sync < 32 * avctx->channels) { /* resynching */
+                    s->sync++;
+                    d0 = d1 = 0x69;
+                }
+            }
+            src += 3;
+
+            dst[0]               = d0;
+            dst[avctx->channels] = d1;
+            dst++;
+        }
+        dst += avctx->channels;
+        s->state ^= 1;
+    }
+
+    *got_frame_ptr = 1;
+    return pcm_samples * 3 * avctx->channels;
+}
+
+AVCodec ff_dop_s24le_decoder = {
+    .name           = "dop_s24le",
+    .priv_data_size = sizeof(DOPContext),
+    .long_name      = NULL_IF_CONFIG_SMALL("DoP (DSD-over-PCM); signed 24-bit little-endian"),
+    .type           = AVMEDIA_TYPE_AUDIO,
+    .id             = AV_CODEC_ID_DOP_S24LE,
+    .init           = decode_init,
+    .decode         = decode_frame,
+    .sample_fmts    = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_DSD,
+                                                    AV_SAMPLE_FMT_NONE },
+};
+
+static av_cold int encode_init(AVCodecContext *avctx)
+{
+    avctx->bits_per_coded_sample = av_get_bits_per_sample(avctx->codec->id);
+    avctx->block_align           = avctx->channels * avctx->bits_per_coded_sample / 8;
+    avctx->bit_rate              = avctx->block_align * avctx->sample_rate * 8;
+    avctx->sample_rate          /= 16;
+    return 0;
+}
+
+static int encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+                            const AVFrame *frame, int *got_packet_ptr)
+{
+    DOPContext * s = avctx->priv_data;
+    int ret, i, ch;
+    const uint8_t *src;
+    uint8_t *dst;
+
+    if (frame->nb_samples % 2)
+        av_log(avctx, AV_LOG_WARNING, "expected mod 16 samples\n");
+
+    if ((ret = ff_alloc_packet2(avctx, avpkt, ((frame->nb_samples) / 2) * 3 * avctx->channels)) < 0)
+        return ret;
+
+    src = frame->data[0];
+    dst = avpkt->data;
+    for (i = 0; i < frame->nb_samples; i += 2) {
+        for (ch = 0; ch < avctx->channels; ch++) {
+            dst[0] = src[avctx->channels];
+            dst[1] = src[0];
+            dst[2] = dop_marker[s->state];
+            src++;
+            dst += 3;
+        }
+        src += avctx->channels;
+        s->state ^= 1;
+    }
+
+    *got_packet_ptr = 1;
+    return 0;
+}
+
+AVCodec ff_dop_s24le_encoder = {
+    .name           = "dop_s24le",
+    .priv_data_size = sizeof(DOPContext),
+    .long_name      = NULL_IF_CONFIG_SMALL("DoP (DSD-over-PCM); signed 24-bit little-endian"),
+    .type           = AVMEDIA_TYPE_AUDIO,
+    .id             = AV_CODEC_ID_DOP_S24LE,
+    .init           = encode_init,
+    .encode2        = encode_frame,
+    .capabilities   = CODEC_CAP_VARIABLE_FRAME_SIZE,
+    .sample_fmts    = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_DSD,
+                                                    AV_SAMPLE_FMT_NONE},
+};
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 8bb2579..593db69 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -3007,6 +3007,7 @@ int av_get_exact_bits_per_sample(enum AVCodecID codec_id)
     case AV_CODEC_ID_PCM_U16BE:
     case AV_CODEC_ID_PCM_U16LE:
         return 16;
+    case AV_CODEC_ID_DOP_S24LE:
     case AV_CODEC_ID_PCM_S24DAUD:
     case AV_CODEC_ID_PCM_S24BE:
     case AV_CODEC_ID_PCM_S24LE:
-- 
1.8.3.2

-- Peter
(A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
TAG •

List of Articles
No. Subject Author Date Views
32 AMP의 설계 방식 - Class A 방식의 앰프 digipine 2017.11.02 1871
31 Any Pretty Girl - Rebekka Bakken Lyrics digipine 2024.08.21 518
30 De-emphasis 개념 정리 file digipine 2017.11.13 3201
29 DSD 2.8M DSF Sample Test Files digipine 2024.11.24 410
28 DSD 음악 파일에 관한 기술 정보 file digipine 2017.11.02 2222
» FFMpeg에서 DOP (DSD-over-PCM) 구현 패치 엉뚱도마뱀 2018.12.20 4938
26 LDAC 코덱으로 블루투스 고음질 음원 재생 file digipine 2017.11.02 1484
25 OP AMP 기본 개념과 NE5532 자료 file digipine 2017.11.02 1387
24 OP Amp 타입과 종류 정리 digipine 2017.11.02 3721
23 OP Amp의 음색 정리 자료 1 digipine 2017.11.02 10504
22 PCM Volume Control 구현 방법 digipine 2022.04.13 1571
21 Phono Amp DIY kit digipine 2023.10.31 1024
20 Sample mp3 files for test file digipine 2022.11.25 948
19 Semibreve DA10S DAC with XMOS 768kHz Oversampling 5 file lizard2019 2024.05.10 818
18 Summary of Sound Characteristics of Electrolytic Capacitors for Audio Tuning lizard2019 2024.12.05 479
17 Test mp3 music files file digipine 2021.01.24 1502
16 TEST용 동영상 모음 01 file digipine 2020.08.26 752
15 TEST용 동영상 모음 02 file digipine 2020.08.26 686
14 TEST용 동영상 모음 03 file digipine 2020.08.26 867
13 WebRTC의 RED Audio Codec에 대해서 1 digipine 2024.04.15 1749
Board Pagination Prev 1 2 Next
/ 2