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
26 진공관 앰프 회로도 및 제작 매뉴얼 file digipine 2017.11.02 3745
25 DSD 음악 파일에 관한 기술 정보 file digipine 2017.11.02 1632
24 OP AMP 기본 개념과 NE5532 자료 file digipine 2017.11.02 651
23 사운드 전용, 통신 채널인 I2S 스펙 file digipine 2017.11.02 9492
22 AMP의 설계 방식 - Class A 방식의 앰프 digipine 2017.11.02 1236
21 음향 측정 프로그램 SOUND ANALYSIS & CALIBRATION SOFTWARES file digipine 2017.11.02 12289
20 LDAC 코덱으로 블루투스 고음질 음원 재생 file digipine 2017.11.02 908
19 OP Amp의 음색 정리 자료 1 digipine 2017.11.02 9142
18 OP Amp 타입과 종류 정리 digipine 2017.11.02 2946
17 저작권이 만료된 클래식 음악 스트리밍 사이트 file digipine 2017.11.02 2890
16 오디오 효과 정리 digipine 2017.11.02 2311
15 De-emphasis 개념 정리 file digipine 2017.11.13 2589
» FFMpeg에서 DOP (DSD-over-PCM) 구현 패치 엉뚱도마뱀 2018.12.20 4220
13 벨소리 : 이시은 - 바람처럼 떠나버린 너 file lizard2019 2019.05.20 590
12 이어폰 드라이버 정리 (다이나믹 VS BA) lizard2019 2020.02.11 1453
11 소음즉정 기준 dB(A) 단위 file lizard2019 2020.05.25 1279
10 소음 dB 측정 방법 file lizard2019 2020.05.25 1603
9 TEST용 동영상 모음 01 file digipine 2020.08.26 258
8 TEST용 동영상 모음 02 file digipine 2020.08.26 202
7 TEST용 동영상 모음 03 file digipine 2020.08.26 394
Board Pagination Prev 1 2 Next
/ 2