Libav
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 Libav.
6  *
7  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
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 samples_per_block; // Number of samples per channel per block
35  int groups_per_block; // Number of 20/24bit sample groups per block
36  uint8_t *extra_samples; // Pointer to leftover samples from a frame
37  int extra_sample_count; // Number of leftover samples in the buffer
39 
41 {
42  PCMDVDContext *s = avctx->priv_data;
43 
44  /* Invalid header to force parsing of the first header */
45  s->last_header = -1;
46  /* reserve space for 8 channels, 3 bytes/sample, 4 samples/block */
47  if (!(s->extra_samples = av_malloc(8 * 3 * 4)))
48  return AVERROR(ENOMEM);
49 
50  return 0;
51 }
52 
54 {
55  PCMDVDContext *s = avctx->priv_data;
56 
58 
59  return 0;
60 }
61 
62 static int pcm_dvd_parse_header(AVCodecContext *avctx, const uint8_t *header)
63 {
64  /* no traces of 44100 and 32000Hz in any commercial software or player */
65  static const uint32_t frequencies[4] = { 48000, 96000, 44100, 32000 };
66  PCMDVDContext *s = avctx->priv_data;
67  int header_int = (header[0] & 0xe0) | (header[1] << 8) | (header[2] << 16);
68 
69  /* early exit if the header didn't change apart from the frame number */
70  if (s->last_header == header_int)
71  return 0;
72 
73  if (avctx->debug & FF_DEBUG_PICT_INFO)
74  av_dlog(avctx, "pcm_dvd_parse_header: header = %02x%02x%02x\n",
75  header[0], header[1], header[2]);
76  /*
77  * header[0] emphasis (1), muse(1), reserved(1), frame number(5)
78  * header[1] quant (2), freq(2), reserved(1), channels(3)
79  * header[2] dynamic range control (0x80 = off)
80  */
81 
82  /* Discard potentially existing leftover samples from old channel layout */
83  s->extra_sample_count = 0;
84 
85  /* get the sample depth and derive the sample format from it */
86  avctx->bits_per_coded_sample = 16 + (header[1] >> 6 & 3) * 4;
87  if (avctx->bits_per_coded_sample == 28) {
88  av_log(avctx, AV_LOG_ERROR, "PCM DVD unsupported sample depth\n");
89  return AVERROR_INVALIDDATA;
90  }
91  avctx->sample_fmt = avctx->bits_per_coded_sample == 16 ? AV_SAMPLE_FMT_S16
94 
95  /* get the sample rate */
96  avctx->sample_rate = frequencies[header[1] >> 4 & 3];
97 
98  /* get the number of channels */
99  avctx->channels = 1 + (header[1] & 7);
100  /* calculate the bitrate */
101  avctx->bit_rate = avctx->channels *
102  avctx->sample_rate *
103  avctx->bits_per_coded_sample;
104 
105  /* 4 samples form a group in 20/24bit PCM on DVD Video.
106  * A block is formed by the number of groups that are
107  * needed to complete a set of samples for each channel. */
108  if (avctx->bits_per_coded_sample == 16) {
109  s->samples_per_block = 1;
110  s->block_size = avctx->channels * 2;
111  } else {
112  switch (avctx->channels) {
113  case 1:
114  case 2:
115  case 4:
116  /* one group has all the samples needed */
117  s->block_size = 4 * avctx->bits_per_coded_sample / 8;
118  s->samples_per_block = 4 / avctx->channels;
119  s->groups_per_block = 1;
120  break;
121  case 8:
122  /* two groups have all the samples needed */
123  s->block_size = 8 * avctx->bits_per_coded_sample / 8;
124  s->samples_per_block = 1;
125  s->groups_per_block = 2;
126  break;
127  default:
128  /* need avctx->channels groups */
129  s->block_size = 4 * avctx->channels *
130  avctx->bits_per_coded_sample / 8;
131  s->samples_per_block = 4;
132  s->groups_per_block = avctx->channels;
133  break;
134  }
135  }
136 
137  if (avctx->debug & FF_DEBUG_PICT_INFO)
138  av_dlog(avctx,
139  "pcm_dvd_parse_header: %d channels, %d bits per sample, %d Hz, %d bit/s\n",
140  avctx->channels, avctx->bits_per_coded_sample,
141  avctx->sample_rate, avctx->bit_rate);
142 
143  s->last_header = header_int;
144 
145  return 0;
146 }
147 
148 static void *pcm_dvd_decode_samples(AVCodecContext *avctx, const uint8_t *src,
149  void *dst, int blocks)
150 {
151  PCMDVDContext *s = avctx->priv_data;
152  int16_t *dst16 = dst;
153  int32_t *dst32 = dst;
154  GetByteContext gb;
155  int i;
156  uint8_t t;
157  int samples;
158 
159  bytestream2_init(&gb, src, blocks * s->block_size);
160  switch (avctx->bits_per_coded_sample) {
161  case 16:
162 #if HAVE_BIGENDIAN
163  bytestream2_get_buffer(&gb, dst16, blocks * s->block_size);
164  dst16 += blocks * s->block_size / 2;
165 #else
166  samples = blocks * avctx->channels;
167  do {
168  *dst16++ = bytestream2_get_be16u(&gb);
169  } while (--samples);
170 #endif
171  return dst16;
172  case 20:
173  do {
174  for (i = s->groups_per_block; i; i--) {
175  dst32[0] = bytestream2_get_be16u(&gb) << 16;
176  dst32[1] = bytestream2_get_be16u(&gb) << 16;
177  dst32[2] = bytestream2_get_be16u(&gb) << 16;
178  dst32[3] = bytestream2_get_be16u(&gb) << 16;
179  t = bytestream2_get_byteu(&gb);
180  *dst32++ += (t & 0xf0) << 8;
181  *dst32++ += (t & 0x0f) << 12;
182  t = bytestream2_get_byteu(&gb);
183  *dst32++ += (t & 0xf0) << 8;
184  *dst32++ += (t & 0x0f) << 12;
185  }
186  } while (--blocks);
187  return dst32;
188  case 24:
189  do {
190  for (i = s->groups_per_block; i; i--) {
191  dst32[0] = bytestream2_get_be16u(&gb) << 16;
192  dst32[1] = bytestream2_get_be16u(&gb) << 16;
193  dst32[2] = bytestream2_get_be16u(&gb) << 16;
194  dst32[3] = bytestream2_get_be16u(&gb) << 16;
195  *dst32++ += bytestream2_get_byteu(&gb) << 8;
196  *dst32++ += bytestream2_get_byteu(&gb) << 8;
197  *dst32++ += bytestream2_get_byteu(&gb) << 8;
198  *dst32++ += bytestream2_get_byteu(&gb) << 8;
199  }
200  } while (--blocks);
201  return dst32;
202  default:
203  return NULL;
204  }
205 }
206 
207 static int pcm_dvd_decode_frame(AVCodecContext *avctx, void *data,
208  int *got_frame_ptr, AVPacket *avpkt)
209 {
210  AVFrame *frame = data;
211  const uint8_t *src = avpkt->data;
212  int buf_size = avpkt->size;
213  PCMDVDContext *s = avctx->priv_data;
214  int retval;
215  int blocks;
216  void *dst;
217 
218  if (buf_size < 3) {
219  av_log(avctx, AV_LOG_ERROR, "PCM packet too small\n");
220  return AVERROR_INVALIDDATA;
221  }
222 
223  if ((retval = pcm_dvd_parse_header(avctx, src)))
224  return retval;
225  src += 3;
226  buf_size -= 3;
227 
228  blocks = (buf_size + s->extra_sample_count) / s->block_size;
229 
230  /* get output buffer */
231  frame->nb_samples = blocks * s->samples_per_block;
232  if ((retval = ff_get_buffer(avctx, frame, 0)) < 0) {
233  av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
234  return retval;
235  }
236  dst = frame->data[0];
237 
238  /* consume leftover samples from last packet */
239  if (s->extra_sample_count) {
240  int missing_samples = s->block_size - s->extra_sample_count;
241  if (buf_size >= missing_samples) {
242  memcpy(s->extra_samples + s->extra_sample_count, src,
243  missing_samples);
244  dst = pcm_dvd_decode_samples(avctx, s->extra_samples, dst, 1);
245  src += missing_samples;
246  buf_size -= missing_samples;
247  s->extra_sample_count = 0;
248  blocks--;
249  } else {
250  /* new packet still doesn't have enough samples */
251  memcpy(s->extra_samples + s->extra_sample_count, src, buf_size);
252  s->extra_sample_count += buf_size;
253  return avpkt->size;
254  }
255  }
256 
257  /* decode remaining complete samples */
258  if (blocks) {
259  pcm_dvd_decode_samples(avctx, src, dst, blocks);
260  buf_size -= blocks * s->block_size;
261  }
262 
263  /* store leftover samples */
264  if (buf_size) {
265  src += blocks * s->block_size;
266  memcpy(s->extra_samples, src, buf_size);
267  s->extra_sample_count = buf_size;
268  }
269 
270  *got_frame_ptr = 1;
271 
272  return avpkt->size;
273 }
274 
276  .name = "pcm_dvd",
277  .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for DVD media"),
278  .type = AVMEDIA_TYPE_AUDIO,
279  .id = AV_CODEC_ID_PCM_DVD,
280  .priv_data_size = sizeof(PCMDVDContext),
284  .capabilities = CODEC_CAP_DR1,
285  .sample_fmts = (const enum AVSampleFormat[]) {
287  }
288 };
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:62
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:54
This structure describes decoded (raw) audio or video data.
Definition: frame.h:135
int size
Definition: avcodec.h:974
static av_cold int pcm_dvd_decode_uninit(AVCodecContext *avctx)
Definition: pcm-dvd.c:53
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:132
int bits_per_raw_sample
Bits per sample/pixel of internal libavcodec pixel/sample format.
Definition: avcodec.h:2530
AVCodec.
Definition: avcodec.h:2812
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
av_dlog(ac->avr, "%d samples - audio_convert: %s to %s (%s)\, len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt), use_generic ? ac->func_descr_generic :ac->func_descr)
static int decode(MimicContext *ctx, int quality, int num_coeffs, int is_iframe)
Definition: mimic.c:275
enum AVSampleFormat sample_fmt
audio sample format
Definition: avcodec.h:1815
uint8_t
#define av_cold
Definition: attributes.h:66
#define FF_DEBUG_PICT_INFO
Definition: avcodec.h:2379
#define CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: avcodec.h:684
const char data[16]
Definition: mxf.c:70
uint8_t * data
Definition: avcodec.h:973
int bits_per_coded_sample
bits per sample/pixel from the demuxer (needed for huffyuv).
Definition: avcodec.h:2523
signed 32 bits
Definition: samplefmt.h:65
static void * pcm_dvd_decode_samples(AVCodecContext *avctx, const uint8_t *src, void *dst, int blocks)
Definition: pcm-dvd.c:148
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:123
int groups_per_block
Definition: pcm-dvd.c:35
#define AVERROR(e)
Definition: error.h:43
static int pcm_dvd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, AVPacket *avpkt)
Definition: pcm-dvd.c:207
sample_fmts
Definition: avconv_filter.c:68
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:145
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:260
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:169
const char * name
Name of the codec implementation.
Definition: avcodec.h:2819
int samples_per_block
Definition: pcm-dvd.c:34
int bit_rate
the average bitrate
Definition: avcodec.h:1114
int extra_sample_count
Definition: pcm-dvd.c:37
int32_t
if(ac->has_optimized_func)
NULL
Definition: eval.c:55
Libavcodec external API header.
uint32_t last_header
Definition: pcm-dvd.c:32
AVSampleFormat
Audio Sample Formats.
Definition: samplefmt.h:61
AV_SAMPLE_FMT_NONE
Definition: avconv_filter.c:68
int sample_rate
samples per second
Definition: avcodec.h:1807
int debug
debug
Definition: avcodec.h:2378
main external API structure.
Definition: avcodec.h:1050
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:490
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: utils.c:612
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:141
static av_cold int pcm_dvd_decode_init(AVCodecContext *avctx)
Definition: pcm-dvd.c:40
common internal api header.
signed 16 bits
Definition: samplefmt.h:64
static av_cold int init(AVCodecParserContext *s)
Definition: h264_parser.c:499
void * priv_data
Definition: avcodec.h:1092
int channels
number of audio channels
Definition: avcodec.h:1808
int block_size
Definition: pcm-dvd.c:33
uint8_t * extra_samples
Definition: pcm-dvd.c:36
This structure stores compressed data.
Definition: avcodec.h:950
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:179
static int pcm_dvd_parse_header(AVCodecContext *avctx, const uint8_t *header)
Definition: pcm-dvd.c:62
AVCodec ff_pcm_dvd_decoder
Definition: pcm-dvd.c:275