00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include "avcodec.h"
00028 #include "bytestream.h"
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00051 static int pcm_bluray_parse_header(AVCodecContext *avctx,
00052 const uint8_t *header)
00053 {
00054 static const uint8_t bits_per_samples[4] = { 0, 16, 20, 24 };
00055 static const uint32_t channel_layouts[16] = {
00056 0, CH_LAYOUT_MONO, 0, CH_LAYOUT_STEREO, CH_LAYOUT_SURROUND,
00057 CH_LAYOUT_2_1, CH_LAYOUT_4POINT0, CH_LAYOUT_2_2, CH_LAYOUT_5POINT0,
00058 CH_LAYOUT_5POINT1, CH_LAYOUT_7POINT0, CH_LAYOUT_7POINT1, 0, 0, 0, 0
00059 };
00060 static const uint8_t channels[16] = {
00061 0, 1, 0, 2, 3, 3, 4, 4, 5, 6, 7, 8, 0, 0, 0, 0
00062 };
00063 uint8_t channel_layout = header[2] >> 4;
00064
00065 if (avctx->debug & FF_DEBUG_PICT_INFO)
00066 dprintf(avctx, "pcm_bluray_parse_header: header = %02x%02x%02x%02x\n",
00067 header[0], header[1], header[2], header[3]);
00068
00069
00070 avctx->bits_per_coded_sample = bits_per_samples[header[3] >> 6];
00071 if (!avctx->bits_per_coded_sample) {
00072 av_log(avctx, AV_LOG_ERROR, "unsupported sample depth (0)\n");
00073 return -1;
00074 }
00075 avctx->sample_fmt = avctx->bits_per_coded_sample == 16 ? SAMPLE_FMT_S16 :
00076 SAMPLE_FMT_S32;
00077
00078
00079 switch (header[2] & 0x0f) {
00080 case 1:
00081 avctx->sample_rate = 48000;
00082 break;
00083 case 4:
00084 avctx->sample_rate = 96000;
00085 break;
00086 case 5:
00087 avctx->sample_rate = 192000;
00088 break;
00089 default:
00090 avctx->sample_rate = 0;
00091 av_log(avctx, AV_LOG_ERROR, "unsupported sample rate (%d)\n",
00092 header[2] & 0x0f);
00093 return -1;
00094 }
00095
00096
00097
00098
00099
00100
00101
00102 avctx->channel_layout = channel_layouts[channel_layout];
00103 avctx->channels = channels[channel_layout];
00104 if (!avctx->channels) {
00105 av_log(avctx, AV_LOG_ERROR, "unsupported channel configuration (%d)\n",
00106 channel_layout);
00107 return -1;
00108 }
00109
00110 avctx->bit_rate = avctx->channels * avctx->sample_rate *
00111 avctx->bits_per_coded_sample;
00112
00113 if (avctx->debug & FF_DEBUG_PICT_INFO)
00114 dprintf(avctx,
00115 "pcm_bluray_parse_header: %d channels, %d bits per sample, %d kHz, %d kbit\n",
00116 avctx->channels, avctx->bits_per_coded_sample,
00117 avctx->sample_rate, avctx->bit_rate);
00118 return 0;
00119 }
00120
00121 static int pcm_bluray_decode_frame(AVCodecContext *avctx,
00122 void *data,
00123 int *data_size,
00124 AVPacket *avpkt)
00125 {
00126 const uint8_t *src = avpkt->data;
00127 int buf_size = avpkt->size;
00128 int num_source_channels, channel, retval;
00129 int sample_size, samples, output_size;
00130 int16_t *dst16 = data;
00131 int32_t *dst32 = data;
00132
00133 if (buf_size < 4) {
00134 av_log(avctx, AV_LOG_ERROR, "PCM packet too small\n");
00135 return -1;
00136 }
00137
00138 if (pcm_bluray_parse_header(avctx, src))
00139 return -1;
00140 src += 4;
00141 buf_size -= 4;
00142
00143
00144 num_source_channels = FFALIGN(avctx->channels, 2);
00145 sample_size = (num_source_channels * avctx->bits_per_coded_sample) >> 3;
00146 samples = buf_size / sample_size;
00147
00148 output_size = samples * avctx->channels *
00149 (avctx->sample_fmt == SAMPLE_FMT_S32 ? 4 : 2);
00150 if (output_size > *data_size) {
00151 av_log(avctx, AV_LOG_ERROR,
00152 "Insufficient output buffer space (%d bytes, needed %d bytes)\n",
00153 *data_size, output_size);
00154 return -1;
00155 }
00156 *data_size = output_size;
00157
00158 if (samples) {
00159 switch (avctx->channel_layout) {
00160
00161 case CH_LAYOUT_STEREO:
00162 case CH_LAYOUT_4POINT0:
00163 case CH_LAYOUT_2_2:
00164 samples *= num_source_channels;
00165 if (SAMPLE_FMT_S16 == avctx->sample_fmt) {
00166 #if HAVE_BIGENDIAN
00167 memcpy(dst16, src, output_size);
00168 #else
00169 do {
00170 *dst16++ = bytestream_get_be16(&src);
00171 } while (--samples);
00172 #endif
00173 } else {
00174 do {
00175 *dst32++ = bytestream_get_be24(&src) << 8;
00176 } while (--samples);
00177 }
00178 break;
00179
00180 case CH_LAYOUT_MONO:
00181 case CH_LAYOUT_SURROUND:
00182 case CH_LAYOUT_2_1:
00183 case CH_LAYOUT_5POINT0:
00184 if (SAMPLE_FMT_S16 == avctx->sample_fmt) {
00185 do {
00186 #if HAVE_BIGENDIAN
00187 memcpy(dst16, src, avctx->channels * 2);
00188 dst16 += avctx->channels;
00189 src += sample_size;
00190 #else
00191 channel = avctx->channels;
00192 do {
00193 *dst16++ = bytestream_get_be16(&src);
00194 } while (--channel);
00195 src += 2;
00196 #endif
00197 } while (--samples);
00198 } else {
00199 do {
00200 channel = avctx->channels;
00201 do {
00202 *dst32++ = bytestream_get_be24(&src) << 8;
00203 } while (--channel);
00204 src += 3;
00205 } while (--samples);
00206 }
00207 break;
00208
00209 case CH_LAYOUT_5POINT1:
00210 if (SAMPLE_FMT_S16 == avctx->sample_fmt) {
00211 do {
00212 dst16[0] = bytestream_get_be16(&src);
00213 dst16[1] = bytestream_get_be16(&src);
00214 dst16[2] = bytestream_get_be16(&src);
00215 dst16[4] = bytestream_get_be16(&src);
00216 dst16[5] = bytestream_get_be16(&src);
00217 dst16[3] = bytestream_get_be16(&src);
00218 dst16 += 6;
00219 } while (--samples);
00220 } else {
00221 do {
00222 dst32[0] = bytestream_get_be24(&src) << 8;
00223 dst32[1] = bytestream_get_be24(&src) << 8;
00224 dst32[2] = bytestream_get_be24(&src) << 8;
00225 dst32[4] = bytestream_get_be24(&src) << 8;
00226 dst32[5] = bytestream_get_be24(&src) << 8;
00227 dst32[3] = bytestream_get_be24(&src) << 8;
00228 dst32 += 6;
00229 } while (--samples);
00230 }
00231 break;
00232
00233 case CH_LAYOUT_7POINT0:
00234 if (SAMPLE_FMT_S16 == avctx->sample_fmt) {
00235 do {
00236 dst16[0] = bytestream_get_be16(&src);
00237 dst16[1] = bytestream_get_be16(&src);
00238 dst16[2] = bytestream_get_be16(&src);
00239 dst16[5] = bytestream_get_be16(&src);
00240 dst16[3] = bytestream_get_be16(&src);
00241 dst16[4] = bytestream_get_be16(&src);
00242 dst16[6] = bytestream_get_be16(&src);
00243 dst16 += 7;
00244 src += 2;
00245 } while (--samples);
00246 } else {
00247 do {
00248 dst32[0] = bytestream_get_be24(&src) << 8;
00249 dst32[1] = bytestream_get_be24(&src) << 8;
00250 dst32[2] = bytestream_get_be24(&src) << 8;
00251 dst32[5] = bytestream_get_be24(&src) << 8;
00252 dst32[3] = bytestream_get_be24(&src) << 8;
00253 dst32[4] = bytestream_get_be24(&src) << 8;
00254 dst32[6] = bytestream_get_be24(&src) << 8;
00255 dst32 += 7;
00256 src += 3;
00257 } while (--samples);
00258 }
00259 break;
00260
00261 case CH_LAYOUT_7POINT1:
00262 if (SAMPLE_FMT_S16 == avctx->sample_fmt) {
00263 do {
00264 dst16[0] = bytestream_get_be16(&src);
00265 dst16[1] = bytestream_get_be16(&src);
00266 dst16[2] = bytestream_get_be16(&src);
00267 dst16[6] = bytestream_get_be16(&src);
00268 dst16[4] = bytestream_get_be16(&src);
00269 dst16[5] = bytestream_get_be16(&src);
00270 dst16[7] = bytestream_get_be16(&src);
00271 dst16[3] = bytestream_get_be16(&src);
00272 dst16 += 8;
00273 } while (--samples);
00274 } else {
00275 do {
00276 dst32[0] = bytestream_get_be24(&src) << 8;
00277 dst32[1] = bytestream_get_be24(&src) << 8;
00278 dst32[2] = bytestream_get_be24(&src) << 8;
00279 dst32[6] = bytestream_get_be24(&src) << 8;
00280 dst32[4] = bytestream_get_be24(&src) << 8;
00281 dst32[5] = bytestream_get_be24(&src) << 8;
00282 dst32[7] = bytestream_get_be24(&src) << 8;
00283 dst32[3] = bytestream_get_be24(&src) << 8;
00284 dst32 += 8;
00285 } while (--samples);
00286 }
00287 break;
00288 }
00289 }
00290
00291 retval = src - avpkt->data;
00292 if (avctx->debug & FF_DEBUG_BITSTREAM)
00293 dprintf(avctx, "pcm_bluray_decode_frame: decoded %d -> %d bytes\n",
00294 retval, *data_size);
00295 return retval;
00296 }
00297
00298 AVCodec pcm_bluray_decoder = {
00299 "pcm_bluray",
00300 AVMEDIA_TYPE_AUDIO,
00301 CODEC_ID_PCM_BLURAY,
00302 0,
00303 NULL,
00304 NULL,
00305 NULL,
00306 pcm_bluray_decode_frame,
00307 .sample_fmts = (const enum SampleFormat[]){SAMPLE_FMT_S16, SAMPLE_FMT_S32,
00308 SAMPLE_FMT_NONE},
00309 .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for Blu-ray media"),
00310 };