• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavcodec/mlp_parser.c

Go to the documentation of this file.
00001 /*
00002  * MLP parser
00003  * Copyright (c) 2007 Ian Caulfield
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00027 #include <stdint.h>
00028 
00029 #include "libavutil/crc.h"
00030 #include "bitstream.h"
00031 #include "parser.h"
00032 #include "mlp_parser.h"
00033 #include "mlp.h"
00034 
00035 static const uint8_t mlp_quants[16] = {
00036     16, 20, 24, 0, 0, 0, 0, 0,
00037      0,  0,  0, 0, 0, 0, 0, 0,
00038 };
00039 
00040 static const uint8_t mlp_channels[32] = {
00041     1, 2, 3, 4, 3, 4, 5, 3, 4, 5, 4, 5, 6, 4, 5, 4,
00042     5, 6, 5, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00043 };
00044 
00045 static const uint8_t thd_chancount[13] = {
00046 //  LR    C   LFE  LRs LRvh  LRc LRrs  Cs   Ts  LRsd  LRw  Cvh  LFE2
00047      2,   1,   1,   2,   2,   2,   2,   1,   1,   2,   2,   1,   1
00048 };
00049 
00050 static int mlp_samplerate(int in)
00051 {
00052     if (in == 0xF)
00053         return 0;
00054 
00055     return (in & 8 ? 44100 : 48000) << (in & 7) ;
00056 }
00057 
00058 static int truehd_channels(int chanmap)
00059 {
00060     int channels = 0, i;
00061 
00062     for (i = 0; i < 13; i++)
00063         channels += thd_chancount[i] * ((chanmap >> i) & 1);
00064 
00065     return channels;
00066 }
00067 
00074 int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb)
00075 {
00076     int ratebits;
00077     uint16_t checksum;
00078 
00079     assert(get_bits_count(gb) == 0);
00080 
00081     if (gb->size_in_bits < 28 << 3) {
00082         av_log(log, AV_LOG_ERROR, "packet too short, unable to read major sync\n");
00083         return -1;
00084     }
00085 
00086     checksum = ff_mlp_checksum16(gb->buffer, 26);
00087     if (checksum != AV_RL16(gb->buffer+26)) {
00088         av_log(log, AV_LOG_ERROR, "major sync info header checksum error\n");
00089         return -1;
00090     }
00091 
00092     if (get_bits_long(gb, 24) != 0xf8726f) /* Sync words */
00093         return -1;
00094 
00095     mh->stream_type = get_bits(gb, 8);
00096 
00097     if (mh->stream_type == 0xbb) {
00098         mh->group1_bits = mlp_quants[get_bits(gb, 4)];
00099         mh->group2_bits = mlp_quants[get_bits(gb, 4)];
00100 
00101         ratebits = get_bits(gb, 4);
00102         mh->group1_samplerate = mlp_samplerate(ratebits);
00103         mh->group2_samplerate = mlp_samplerate(get_bits(gb, 4));
00104 
00105         skip_bits(gb, 11);
00106 
00107         mh->channels_mlp = get_bits(gb, 5);
00108     } else if (mh->stream_type == 0xba) {
00109         mh->group1_bits = 24; // TODO: Is this information actually conveyed anywhere?
00110         mh->group2_bits = 0;
00111 
00112         ratebits = get_bits(gb, 4);
00113         mh->group1_samplerate = mlp_samplerate(ratebits);
00114         mh->group2_samplerate = 0;
00115 
00116         skip_bits(gb, 8);
00117 
00118         mh->channels_thd_stream1 = get_bits(gb, 5);
00119 
00120         skip_bits(gb, 2);
00121 
00122         mh->channels_thd_stream2 = get_bits(gb, 13);
00123     } else
00124         return -1;
00125 
00126     mh->access_unit_size = 40 << (ratebits & 7);
00127     mh->access_unit_size_pow2 = 64 << (ratebits & 7);
00128 
00129     skip_bits_long(gb, 48);
00130 
00131     mh->is_vbr = get_bits1(gb);
00132 
00133     mh->peak_bitrate = (get_bits(gb, 15) * mh->group1_samplerate + 8) >> 4;
00134 
00135     mh->num_substreams = get_bits(gb, 4);
00136 
00137     skip_bits_long(gb, 4 + 11 * 8);
00138 
00139     return 0;
00140 }
00141 
00142 typedef struct MLPParseContext
00143 {
00144     ParseContext pc;
00145 
00146     int bytes_left;
00147 
00148     int in_sync;
00149 
00150     int num_substreams;
00151 } MLPParseContext;
00152 
00153 static av_cold int mlp_init(AVCodecParserContext *s)
00154 {
00155     ff_mlp_init_crc();
00156     return 0;
00157 }
00158 
00159 static int mlp_parse(AVCodecParserContext *s,
00160                      AVCodecContext *avctx,
00161                      const uint8_t **poutbuf, int *poutbuf_size,
00162                      const uint8_t *buf, int buf_size)
00163 {
00164     MLPParseContext *mp = s->priv_data;
00165     int sync_present;
00166     uint8_t parity_bits;
00167     int next;
00168     int i, p = 0;
00169 
00170     *poutbuf_size = 0;
00171     if (buf_size == 0)
00172         return 0;
00173 
00174     if (!mp->in_sync) {
00175         // Not in sync - find a major sync header
00176 
00177         for (i = 0; i < buf_size; i++) {
00178             mp->pc.state = (mp->pc.state << 8) | buf[i];
00179             if ((mp->pc.state & 0xfffffffe) == 0xf8726fba) {
00180                 mp->in_sync = 1;
00181                 mp->bytes_left = 0;
00182                 break;
00183             }
00184         }
00185 
00186         if (!mp->in_sync) {
00187             ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size);
00188             return buf_size;
00189         }
00190 
00191         ff_combine_frame(&mp->pc, i - 7, &buf, &buf_size);
00192 
00193         return i - 7;
00194     }
00195 
00196     if (mp->bytes_left == 0) {
00197         // Find length of this packet
00198 
00199         /* Copy overread bytes from last frame into buffer. */
00200         for(; mp->pc.overread>0; mp->pc.overread--) {
00201             mp->pc.buffer[mp->pc.index++]= mp->pc.buffer[mp->pc.overread_index++];
00202         }
00203 
00204         if (mp->pc.index + buf_size < 2) {
00205             ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size);
00206             return buf_size;
00207         }
00208 
00209         mp->bytes_left = ((mp->pc.index > 0 ? mp->pc.buffer[0] : buf[0]) << 8)
00210                        |  (mp->pc.index > 1 ? mp->pc.buffer[1] : buf[1-mp->pc.index]);
00211         mp->bytes_left = (mp->bytes_left & 0xfff) * 2;
00212         mp->bytes_left -= mp->pc.index;
00213     }
00214 
00215     next = (mp->bytes_left > buf_size) ? END_NOT_FOUND : mp->bytes_left;
00216 
00217     if (ff_combine_frame(&mp->pc, next, &buf, &buf_size) < 0) {
00218         mp->bytes_left -= buf_size;
00219         return buf_size;
00220     }
00221 
00222     mp->bytes_left = 0;
00223 
00224     sync_present = (AV_RB32(buf + 4) & 0xfffffffe) == 0xf8726fba;
00225 
00226     if (!sync_present) {
00227         /* The first nibble of a frame is a parity check of the 4-byte
00228          * access unit header and all the 2- or 4-byte substream headers. */
00229         // Only check when this isn't a sync frame - syncs have a checksum.
00230 
00231         parity_bits = 0;
00232         for (i = -1; i < mp->num_substreams; i++) {
00233             parity_bits ^= buf[p++];
00234             parity_bits ^= buf[p++];
00235 
00236             if (i < 0 || buf[p-2] & 0x80) {
00237                 parity_bits ^= buf[p++];
00238                 parity_bits ^= buf[p++];
00239             }
00240         }
00241 
00242         if ((((parity_bits >> 4) ^ parity_bits) & 0xF) != 0xF) {
00243             av_log(avctx, AV_LOG_INFO, "mlpparse: Parity check failed.\n");
00244             goto lost_sync;
00245         }
00246     } else {
00247         GetBitContext gb;
00248         MLPHeaderInfo mh;
00249 
00250         init_get_bits(&gb, buf + 4, (buf_size - 4) << 3);
00251         if (ff_mlp_read_major_sync(avctx, &mh, &gb) < 0)
00252             goto lost_sync;
00253 
00254         avctx->bits_per_raw_sample = mh.group1_bits;
00255         if (avctx->bits_per_raw_sample > 16)
00256             avctx->sample_fmt = SAMPLE_FMT_S32;
00257         else
00258             avctx->sample_fmt = SAMPLE_FMT_S16;
00259         avctx->sample_rate = mh.group1_samplerate;
00260         avctx->frame_size = mh.access_unit_size;
00261 
00262         if (mh.stream_type == 0xbb) {
00263             /* MLP stream */
00264             avctx->channels = mlp_channels[mh.channels_mlp];
00265         } else { /* mh.stream_type == 0xba */
00266             /* TrueHD stream */
00267             if (mh.channels_thd_stream2)
00268                 avctx->channels = truehd_channels(mh.channels_thd_stream2);
00269             else
00270                 avctx->channels = truehd_channels(mh.channels_thd_stream1);
00271         }
00272 
00273         if (!mh.is_vbr) /* Stream is CBR */
00274             avctx->bit_rate = mh.peak_bitrate;
00275 
00276         mp->num_substreams = mh.num_substreams;
00277     }
00278 
00279     *poutbuf = buf;
00280     *poutbuf_size = buf_size;
00281 
00282     return next;
00283 
00284 lost_sync:
00285     mp->in_sync = 0;
00286     return 1;
00287 }
00288 
00289 AVCodecParser mlp_parser = {
00290     { CODEC_ID_MLP },
00291     sizeof(MLPParseContext),
00292     mlp_init,
00293     mlp_parse,
00294     NULL,
00295 };

Generated on Sat Feb 16 2013 09:23:12 for ffmpeg by  doxygen 1.7.1