FFmpeg
pcm-dvd.c
Go to the documentation of this file.
1 /*
2  * LPCM codecs for PCM formats found in Video DVD streams
3  * Copyright (c) 2013 Christian Schmidt
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 /**
23  * @file
24  * LPCM codecs for PCM formats found in Video DVD streams
25  */
26 
27 #include "avcodec.h"
28 #include "bytestream.h"
29 #include "internal.h"
30 
31 typedef struct PCMDVDContext {
32  uint32_t last_header; // Cached header to see if parsing is needed
33  int block_size; // Size of a block of samples in bytes
34  int last_block_size; // Size of the last block of samples in bytes
35  int samples_per_block; // Number of samples per channel per block
36  int groups_per_block; // Number of 20/24-bit sample groups per block
37  int extra_sample_count; // Number of leftover samples in the buffer
38  uint8_t extra_samples[8 * 3 * 4]; // Space for leftover samples from a frame
39  // (8 channels, 3B/sample, 4 samples/block)
41 
43 {
44  PCMDVDContext *s = avctx->priv_data;
45 
46  /* Invalid header to force parsing of the first header */
47  s->last_header = -1;
48 
49  return 0;
50 }
51 
53 {
54  /* no traces of 44100 and 32000Hz in any commercial software or player */
55  static const uint32_t frequencies[4] = { 48000, 96000, 44100, 32000 };
56  PCMDVDContext *s = avctx->priv_data;
57  int header_int = (header[0] & 0xe0) | (header[1] << 8) | (header[2] << 16);
58 
59  /* early exit if the header didn't change apart from the frame number */
60  if (s->last_header == header_int)
61  return 0;
62  s->last_header = -1;
63 
64  if (avctx->debug & FF_DEBUG_PICT_INFO)
65  av_log(avctx, AV_LOG_DEBUG, "pcm_dvd_parse_header: header = %02x%02x%02x\n",
66  header[0], header[1], header[2]);
67  /*
68  * header[0] emphasis (1), muse(1), reserved(1), frame number(5)
69  * header[1] quant (2), freq(2), reserved(1), channels(3)
70  * header[2] dynamic range control (0x80 = off)
71  */
72 
73  /* Discard potentially existing leftover samples from old channel layout */
74  s->extra_sample_count = 0;
75 
76  /* get the sample depth and derive the sample format from it */
77  avctx->bits_per_coded_sample = 16 + (header[1] >> 6 & 3) * 4;
78  if (avctx->bits_per_coded_sample == 28) {
79  av_log(avctx, AV_LOG_ERROR,
80  "PCM DVD unsupported sample depth %i\n",
81  avctx->bits_per_coded_sample);
82  return AVERROR_INVALIDDATA;
83  }
84  avctx->sample_fmt = avctx->bits_per_coded_sample == 16 ? AV_SAMPLE_FMT_S16
87 
88  /* get the sample rate */
89  avctx->sample_rate = frequencies[header[1] >> 4 & 3];
90 
91  /* get the number of channels */
92  avctx->channels = 1 + (header[1] & 7);
93  /* calculate the bitrate */
94  avctx->bit_rate = avctx->channels *
95  avctx->sample_rate *
96  avctx->bits_per_coded_sample;
97 
98  /* 4 samples form a group in 20/24-bit PCM on DVD Video.
99  * A block is formed by the number of groups that are
100  * needed to complete a set of samples for each channel. */
101  if (avctx->bits_per_coded_sample == 16) {
102  s->samples_per_block = 1;
103  s->block_size = avctx->channels * 2;
104  } else {
105  switch (avctx->channels) {
106  case 1:
107  case 2:
108  case 4:
109  /* one group has all the samples needed */
110  s->block_size = 4 * avctx->bits_per_coded_sample / 8;
111  s->samples_per_block = 4 / avctx->channels;
112  s->groups_per_block = 1;
113  break;
114  case 8:
115  /* two groups have all the samples needed */
116  s->block_size = 8 * avctx->bits_per_coded_sample / 8;
117  s->samples_per_block = 1;
118  s->groups_per_block = 2;
119  break;
120  default:
121  /* need avctx->channels groups */
122  s->block_size = 4 * avctx->channels *
123  avctx->bits_per_coded_sample / 8;
124  s->samples_per_block = 4;
125  s->groups_per_block = avctx->channels;
126  break;
127  }
128  }
129 
130  if (avctx->debug & FF_DEBUG_PICT_INFO)
131  ff_dlog(avctx,
132  "pcm_dvd_parse_header: %d channels, %d bits per sample, %d Hz, %"PRId64" bit/s\n",
133  avctx->channels, avctx->bits_per_coded_sample,
134  avctx->sample_rate, avctx->bit_rate);
135 
136  s->last_header = header_int;
137 
138  return 0;
139 }
140 
141 static void *pcm_dvd_decode_samples(AVCodecContext *avctx, const uint8_t *src,
142  void *dst, int blocks)
143 {
144  PCMDVDContext *s = avctx->priv_data;
145  int16_t *dst16 = dst;
146  int32_t *dst32 = dst;
147  GetByteContext gb;
148  int i;
149  uint8_t t;
150 
151  bytestream2_init(&gb, src, blocks * s->block_size);
152  switch (avctx->bits_per_coded_sample) {
153  case 16: {
154 #if HAVE_BIGENDIAN
155  bytestream2_get_buffer(&gb, dst16, blocks * s->block_size);
156  dst16 += blocks * s->block_size / 2;
157 #else
158  int samples = blocks * avctx->channels;
159  do {
160  *dst16++ = bytestream2_get_be16u(&gb);
161  } while (--samples);
162 #endif
163  return dst16;
164  }
165  case 20:
166  if (avctx->channels == 1) {
167  do {
168  for (i = 2; i; i--) {
169  dst32[0] = bytestream2_get_be16u(&gb) << 16;
170  dst32[1] = bytestream2_get_be16u(&gb) << 16;
171  t = bytestream2_get_byteu(&gb);
172  *dst32++ += (t & 0xf0) << 8;
173  *dst32++ += (t & 0x0f) << 12;
174  }
175  } while (--blocks);
176  } else {
177  do {
178  for (i = s->groups_per_block; i; i--) {
179  dst32[0] = bytestream2_get_be16u(&gb) << 16;
180  dst32[1] = bytestream2_get_be16u(&gb) << 16;
181  dst32[2] = bytestream2_get_be16u(&gb) << 16;
182  dst32[3] = bytestream2_get_be16u(&gb) << 16;
183  t = bytestream2_get_byteu(&gb);
184  *dst32++ += (t & 0xf0) << 8;
185  *dst32++ += (t & 0x0f) << 12;
186  t = bytestream2_get_byteu(&gb);
187  *dst32++ += (t & 0xf0) << 8;
188  *dst32++ += (t & 0x0f) << 12;
189  }
190  } while (--blocks);
191  }
192  return dst32;
193  case 24:
194  if (avctx->channels == 1) {
195  do {
196  for (i = 2; i; i--) {
197  dst32[0] = bytestream2_get_be16u(&gb) << 16;
198  dst32[1] = bytestream2_get_be16u(&gb) << 16;
199  *dst32++ += bytestream2_get_byteu(&gb) << 8;
200  *dst32++ += bytestream2_get_byteu(&gb) << 8;
201  }
202  } while (--blocks);
203  } else {
204  do {
205  for (i = s->groups_per_block; i; i--) {
206  dst32[0] = bytestream2_get_be16u(&gb) << 16;
207  dst32[1] = bytestream2_get_be16u(&gb) << 16;
208  dst32[2] = bytestream2_get_be16u(&gb) << 16;
209  dst32[3] = bytestream2_get_be16u(&gb) << 16;
210  *dst32++ += bytestream2_get_byteu(&gb) << 8;
211  *dst32++ += bytestream2_get_byteu(&gb) << 8;
212  *dst32++ += bytestream2_get_byteu(&gb) << 8;
213  *dst32++ += bytestream2_get_byteu(&gb) << 8;
214  }
215  } while (--blocks);
216  }
217  return dst32;
218  default:
219  return NULL;
220  }
221 }
222 
223 static int pcm_dvd_decode_frame(AVCodecContext *avctx, void *data,
224  int *got_frame_ptr, AVPacket *avpkt)
225 {
226  AVFrame *frame = data;
227  const uint8_t *src = avpkt->data;
228  int buf_size = avpkt->size;
229  PCMDVDContext *s = avctx->priv_data;
230  int retval;
231  int blocks;
232  void *dst;
233 
234  if (buf_size < 3) {
235  av_log(avctx, AV_LOG_ERROR, "PCM packet too small\n");
236  return AVERROR_INVALIDDATA;
237  }
238 
239  if ((retval = pcm_dvd_parse_header(avctx, src)))
240  return retval;
241  if (s->last_block_size && s->last_block_size != s->block_size) {
242  av_log(avctx, AV_LOG_WARNING, "block_size has changed %d != %d\n", s->last_block_size, s->block_size);
243  s->extra_sample_count = 0;
244  }
245  s->last_block_size = s->block_size;
246  src += 3;
247  buf_size -= 3;
248 
249  blocks = (buf_size + s->extra_sample_count) / s->block_size;
250 
251  /* get output buffer */
252  frame->nb_samples = blocks * s->samples_per_block;
253  if ((retval = ff_get_buffer(avctx, frame, 0)) < 0)
254  return retval;
255  dst = frame->data[0];
256 
257  /* consume leftover samples from last packet */
258  if (s->extra_sample_count) {
259  int missing_samples = s->block_size - s->extra_sample_count;
260  if (buf_size >= missing_samples) {
261  memcpy(s->extra_samples + s->extra_sample_count, src,
262  missing_samples);
263  dst = pcm_dvd_decode_samples(avctx, s->extra_samples, dst, 1);
264  src += missing_samples;
265  buf_size -= missing_samples;
266  s->extra_sample_count = 0;
267  blocks--;
268  } else {
269  /* new packet still doesn't have enough samples */
270  memcpy(s->extra_samples + s->extra_sample_count, src, buf_size);
271  s->extra_sample_count += buf_size;
272  return avpkt->size;
273  }
274  }
275 
276  /* decode remaining complete samples */
277  if (blocks) {
278  pcm_dvd_decode_samples(avctx, src, dst, blocks);
279  buf_size -= blocks * s->block_size;
280  }
281 
282  /* store leftover samples */
283  if (buf_size) {
284  src += blocks * s->block_size;
285  memcpy(s->extra_samples, src, buf_size);
286  s->extra_sample_count = buf_size;
287  }
288 
289  *got_frame_ptr = 1;
290 
291  return avpkt->size;
292 }
293 
295  .name = "pcm_dvd",
296  .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for DVD media"),
297  .type = AVMEDIA_TYPE_AUDIO,
298  .id = AV_CODEC_ID_PCM_DVD,
299  .priv_data_size = sizeof(PCMDVDContext),
302  .capabilities = AV_CODEC_CAP_DR1,
303  .sample_fmts = (const enum AVSampleFormat[]) {
305  }
306 };
uint8_t header[3]
Definition: pcm-dvdenc.c:27
#define NULL
Definition: coverity.c:32
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
This structure describes decoded (raw) audio or video data.
Definition: frame.h:308
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
uint8_t extra_samples[8 *3 *4]
Definition: pcm-dvd.c:38
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:200
int64_t bit_rate
the average bitrate
Definition: avcodec.h:576
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int size
Definition: packet.h:364
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137
int bits_per_raw_sample
Bits per sample/pixel of internal libavcodec pixel/sample format.
Definition: avcodec.h:1757
AVCodec.
Definition: codec.h:190
static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, FILE *outfile)
Definition: decode_audio.c:71
enum AVSampleFormat sample_fmt
audio sample format
Definition: avcodec.h:1194
uint8_t
#define av_cold
Definition: attributes.h:88
#define FF_DEBUG_PICT_INFO
Definition: avcodec.h:1612
uint8_t * data
Definition: packet.h:363
#define ff_dlog(a,...)
int bits_per_coded_sample
bits per sample/pixel from the demuxer (needed for huffyuv).
Definition: avcodec.h:1750
signed 32 bits
Definition: samplefmt.h:62
static void * pcm_dvd_decode_samples(AVCodecContext *avctx, const uint8_t *src, void *dst, int blocks)
Definition: pcm-dvd.c:141
#define av_log(a,...)
#define src
Definition: vp8dsp.c:254
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
int groups_per_block
Definition: pcm-dvd.c:36
static int pcm_dvd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, AVPacket *avpkt)
Definition: pcm-dvd.c:223
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:153
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:267
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:215
const char * name
Name of the codec implementation.
Definition: codec.h:197
int samples_per_block
Definition: pcm-dvd.c:35
int last_block_size
Definition: pcm-dvd.c:34
int extra_sample_count
Definition: pcm-dvd.c:37
int32_t
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
#define s(width, name)
Definition: cbs_vp9.c:257
if(ret)
Libavcodec external API header.
uint32_t last_header
Definition: pcm-dvd.c:32
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:58
int sample_rate
samples per second
Definition: avcodec.h:1186
int debug
debug
Definition: avcodec.h:1611
main external API structure.
Definition: avcodec.h:526
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1879
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:322
static av_cold int pcm_dvd_decode_init(AVCodecContext *avctx)
Definition: pcm-dvd.c:42
common internal api header.
signed 16 bits
Definition: samplefmt.h:61
void * priv_data
Definition: avcodec.h:553
int channels
number of audio channels
Definition: avcodec.h:1187
static enum AVSampleFormat sample_fmts[]
Definition: adpcmenc.c:845
Filter the word “frame” indicates either a video frame or a group of audio samples
int block_size
Definition: pcm-dvd.c:33
This structure stores compressed data.
Definition: packet.h:340
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:374
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:50
static int pcm_dvd_parse_header(AVCodecContext *avctx, const uint8_t *header)
Definition: pcm-dvd.c:52
int i
Definition: input.c:407
AVCodec ff_pcm_dvd_decoder
Definition: pcm-dvd.c:294