GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/pcm-dvdenc.c Lines: 0 94 0.0 %
Date: 2019-11-20 04:07:19 Branches: 0 32 0.0 %

Line Branch Exec Source
1
/*
2
 * LPCM codecs for PCM formats found in Video DVD streams
3
 * Copyright (c) 2018 Paul B Mahol
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
22
#include "avcodec.h"
23
#include "bytestream.h"
24
#include "internal.h"
25
26
typedef struct PCMDVDContext {
27
    uint8_t header[3];       // Header added to every frame
28
    int block_size;          // Size of a block of samples in bytes
29
    int samples_per_block;   // Number of samples per channel per block
30
    int groups_per_block;    // Number of 20/24-bit sample groups per block
31
    uint8_t *extra_samples;  // Pointer to leftover samples from a frame
32
    int extra_sample_count;  // Number of leftover samples in the buffer
33
} PCMDVDContext;
34
35
static av_cold int pcm_dvd_encode_init(AVCodecContext *avctx)
36
{
37
    PCMDVDContext *s = avctx->priv_data;
38
    int quant, freq, frame_size;
39
40
    switch (avctx->sample_rate) {
41
    case 48000:
42
        freq = 0;
43
        break;
44
    case 96000:
45
        freq = 1;
46
        break;
47
    }
48
49
    switch (avctx->sample_fmt) {
50
    case AV_SAMPLE_FMT_S16:
51
        avctx->bits_per_coded_sample = 16;
52
        quant = 0;
53
        break;
54
    case AV_SAMPLE_FMT_S32:
55
        avctx->bits_per_coded_sample = 24;
56
        quant = 2;
57
        break;
58
    }
59
60
    avctx->bits_per_coded_sample = 16 + quant * 4;
61
    avctx->block_align           = avctx->channels * avctx->bits_per_coded_sample / 8;
62
    avctx->bit_rate              = avctx->block_align * 8LL * avctx->sample_rate;
63
    if (avctx->bit_rate > 9800000) {
64
        av_log(avctx, AV_LOG_ERROR, "Too big bitrate: reduce sample rate, bitdepth or channels.\n");
65
        return AVERROR(EINVAL);
66
    }
67
68
    if (avctx->sample_fmt == AV_SAMPLE_FMT_S16) {
69
        s->samples_per_block = 1;
70
        s->block_size        = avctx->channels * 2;
71
        frame_size           = 2008 / s->block_size;
72
    } else {
73
        switch (avctx->channels) {
74
        case 1:
75
        case 2:
76
        case 4:
77
            /* one group has all the samples needed */
78
            s->block_size        = 4 * avctx->bits_per_coded_sample / 8;
79
            s->samples_per_block = 4 / avctx->channels;
80
            s->groups_per_block  = 1;
81
            break;
82
        case 8:
83
            /* two groups have all the samples needed */
84
            s->block_size        = 8 * avctx->bits_per_coded_sample / 8;
85
            s->samples_per_block = 1;
86
            s->groups_per_block  = 2;
87
            break;
88
        default:
89
            /* need avctx->channels groups */
90
            s->block_size        = 4 * avctx->channels *
91
                                   avctx->bits_per_coded_sample / 8;
92
            s->samples_per_block = 4;
93
            s->groups_per_block  = avctx->channels;
94
            break;
95
        }
96
97
        frame_size = FFALIGN(2008 / s->block_size, s->samples_per_block);
98
    }
99
100
    s->header[0] = 0x0c;
101
    s->header[1] = (quant << 6) | (freq << 4) | (avctx->channels - 1);
102
    s->header[2] = 0x80;
103
104
    if (!avctx->frame_size)
105
        avctx->frame_size = frame_size;
106
107
    return 0;
108
}
109
110
static int pcm_dvd_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
111
                                const AVFrame *frame, int *got_packet_ptr)
112
{
113
    PCMDVDContext *s = avctx->priv_data;
114
    int samples = frame->nb_samples * avctx->channels;
115
    int64_t pkt_size = (frame->nb_samples / s->samples_per_block) * s->block_size + 3;
116
    int blocks = (pkt_size - 3) / s->block_size;
117
    const int16_t *src16;
118
    const int32_t *src32;
119
    PutByteContext pb;
120
    int ret;
121
122
    if ((ret = ff_alloc_packet2(avctx, avpkt, pkt_size, 0)) < 0)
123
        return ret;
124
125
    memcpy(avpkt->data, s->header, 3);
126
127
    src16 = (const int16_t *)frame->data[0];
128
    src32 = (const int32_t *)frame->data[0];
129
130
    bytestream2_init_writer(&pb, avpkt->data + 3, avpkt->size - 3);
131
132
    switch (avctx->sample_fmt) {
133
    case AV_SAMPLE_FMT_S16:
134
        do {
135
            bytestream2_put_be16(&pb, *src16++);
136
        } while (--samples);
137
        break;
138
    case AV_SAMPLE_FMT_S32:
139
        if (avctx->channels == 1) {
140
            do {
141
                for (int i = 2; i; i--) {
142
                    bytestream2_put_be16(&pb, src32[0] >> 16);
143
                    bytestream2_put_be16(&pb, src32[1] >> 16);
144
                    bytestream2_put_byte(&pb, (*src32++) >> 24);
145
                    bytestream2_put_byte(&pb, (*src32++) >> 24);
146
                }
147
            } while (--blocks);
148
        } else {
149
            do {
150
                for (int i = s->groups_per_block; i; i--) {
151
                    bytestream2_put_be16(&pb, src32[0] >> 16);
152
                    bytestream2_put_be16(&pb, src32[1] >> 16);
153
                    bytestream2_put_be16(&pb, src32[2] >> 16);
154
                    bytestream2_put_be16(&pb, src32[3] >> 16);
155
                    bytestream2_put_byte(&pb, (*src32++) >> 24);
156
                    bytestream2_put_byte(&pb, (*src32++) >> 24);
157
                    bytestream2_put_byte(&pb, (*src32++) >> 24);
158
                    bytestream2_put_byte(&pb, (*src32++) >> 24);
159
                }
160
            } while (--blocks);
161
        }
162
        break;
163
    }
164
165
    avpkt->pts      = frame->pts;
166
    avpkt->size     = pkt_size;
167
    avpkt->duration = ff_samples_to_time_base(avctx, frame->nb_samples);
168
    *got_packet_ptr = 1;
169
170
    return 0;
171
}
172
173
static av_cold int pcm_dvd_encode_close(AVCodecContext *avctx)
174
{
175
    return 0;
176
}
177
178
AVCodec ff_pcm_dvd_encoder = {
179
    .name           = "pcm_dvd",
180
    .long_name      = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for DVD media"),
181
    .type           = AVMEDIA_TYPE_AUDIO,
182
    .id             = AV_CODEC_ID_PCM_DVD,
183
    .priv_data_size = sizeof(PCMDVDContext),
184
    .init           = pcm_dvd_encode_init,
185
    .close          = pcm_dvd_encode_close,
186
    .encode2        = pcm_dvd_encode_frame,
187
    .capabilities   = AV_CODEC_CAP_SMALL_LAST_FRAME,
188
    .supported_samplerates = (const int[]) { 48000, 96000, 0},
189
    .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO,
190
                                            AV_CH_LAYOUT_STEREO,
191
                                            AV_CH_LAYOUT_5POINT1,
192
                                            AV_CH_LAYOUT_7POINT1,
193
                                            0 },
194
    .sample_fmts    = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
195
                                                     AV_SAMPLE_FMT_S32,
196
                                                     AV_SAMPLE_FMT_NONE },
197
};