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
30 앰프 회로에서 콘덴서, 캐패시터의 역활 lizard2019 2024.11.27 9
29 DSD 2.8M DSF Sample Test Files digipine 2024.11.24 28
28 Any Pretty Girl - Rebekka Bakken Lyrics digipine 2024.08.21 120
27 Semibreve DA10S DAC with XMOS 768kHz Oversampling 5 file lizard2019 2024.05.10 388
26 WebRTC의 RED Audio Codec에 대해서 1 digipine 2024.04.15 1154
25 Phono Amp DIY kit digipine 2023.10.31 498
24 Sample mp3 files for test file digipine 2022.11.25 539
23 PCM Volume Control 구현 방법 digipine 2022.04.13 1021
22 헤드폰과 스피커 테스트를 위한 Tone Sound File 모음 file digipine 2022.02.25 1053
21 Test mp3 music files file digipine 2021.01.24 1108
20 TEST용 동영상 모음 03 file digipine 2020.08.26 555
19 TEST용 동영상 모음 02 file digipine 2020.08.26 373
18 TEST용 동영상 모음 01 file digipine 2020.08.26 440
17 소음 dB 측정 방법 file lizard2019 2020.05.25 1864
16 소음즉정 기준 dB(A) 단위 file lizard2019 2020.05.25 1503
15 이어폰 드라이버 정리 (다이나믹 VS BA) lizard2019 2020.02.11 1667
14 벨소리 : 이시은 - 바람처럼 떠나버린 너 file lizard2019 2019.05.20 762
» FFMpeg에서 DOP (DSD-over-PCM) 구현 패치 엉뚱도마뱀 2018.12.20 4466
12 De-emphasis 개념 정리 file digipine 2017.11.13 2796
11 오디오 효과 정리 digipine 2017.11.02 2519
Board Pagination Prev 1 2 Next
/ 2