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
25 Phono Amp DIY kit digipine 2023.10.31 178
24 TEST용 동영상 모음 02 file digipine 2020.08.26 202
23 TEST용 동영상 모음 01 file digipine 2020.08.26 258
22 Sample mp3 files for test file digipine 2022.11.25 316
21 TEST용 동영상 모음 03 file digipine 2020.08.26 394
20 헤드폰과 스피커 테스트를 위한 Tone Sound File 모음 file digipine 2022.02.25 552
19 벨소리 : 이시은 - 바람처럼 떠나버린 너 file lizard2019 2019.05.20 590
18 PCM Volume Control 구현 방법 digipine 2022.04.13 616
17 OP AMP 기본 개념과 NE5532 자료 file digipine 2017.11.02 650
16 Test mp3 music files file digipine 2021.01.24 893
15 LDAC 코덱으로 블루투스 고음질 음원 재생 file digipine 2017.11.02 908
14 AMP의 설계 방식 - Class A 방식의 앰프 digipine 2017.11.02 1234
13 소음즉정 기준 dB(A) 단위 file lizard2019 2020.05.25 1274
12 이어폰 드라이버 정리 (다이나믹 VS BA) lizard2019 2020.02.11 1453
11 소음 dB 측정 방법 file lizard2019 2020.05.25 1603
10 DSD 음악 파일에 관한 기술 정보 file digipine 2017.11.02 1631
9 오디오 효과 정리 digipine 2017.11.02 2310
8 De-emphasis 개념 정리 file digipine 2017.11.13 2588
7 저작권이 만료된 클래식 음악 스트리밍 사이트 file digipine 2017.11.02 2890
6 OP Amp 타입과 종류 정리 digipine 2017.11.02 2946
Board Pagination Prev 1 2 Next
/ 2