• 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 "get_bits.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                 // ignore if we do not have the data for the start of header
00181                 mp->pc.index + i >= 7) {
00182                 mp->in_sync = 1;
00183                 mp->bytes_left = 0;
00184                 break;
00185             }
00186         }
00187 
00188         if (!mp->in_sync) {
00189             ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size);
00190             return buf_size;
00191         }
00192 
00193         ff_combine_frame(&mp->pc, i - 7, &buf, &buf_size);
00194 
00195         return i - 7;
00196     }
00197 
00198     if (mp->bytes_left == 0) {
00199         // Find length of this packet
00200 
00201         /* Copy overread bytes from last frame into buffer. */
00202         for(; mp->pc.overread>0; mp->pc.overread--) {
00203             mp->pc.buffer[mp->pc.index++]= mp->pc.buffer[mp->pc.overread_index++];
00204         }
00205 
00206         if (mp->pc.index + buf_size < 2) {
00207             ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size);
00208             return buf_size;
00209         }
00210 
00211         mp->bytes_left = ((mp->pc.index > 0 ? mp->pc.buffer[0] : buf[0]) << 8)
00212                        |  (mp->pc.index > 1 ? mp->pc.buffer[1] : buf[1-mp->pc.index]);
00213         mp->bytes_left = (mp->bytes_left & 0xfff) * 2;
00214         mp->bytes_left -= mp->pc.index;
00215     }
00216 
00217     next = (mp->bytes_left > buf_size) ? END_NOT_FOUND : mp->bytes_left;
00218 
00219     if (ff_combine_frame(&mp->pc, next, &buf, &buf_size) < 0) {
00220         mp->bytes_left -= buf_size;
00221         return buf_size;
00222     }
00223 
00224     mp->bytes_left = 0;
00225 
00226     sync_present = (AV_RB32(buf + 4) & 0xfffffffe) == 0xf8726fba;
00227 
00228     if (!sync_present) {
00229         /* The first nibble of a frame is a parity check of the 4-byte
00230          * access unit header and all the 2- or 4-byte substream headers. */
00231         // Only check when this isn't a sync frame - syncs have a checksum.
00232 
00233         parity_bits = 0;
00234         for (i = -1; i < mp->num_substreams; i++) {
00235             parity_bits ^= buf[p++];
00236             parity_bits ^= buf[p++];
00237 
00238             if (i < 0 || buf[p-2] & 0x80) {
00239                 parity_bits ^= buf[p++];
00240                 parity_bits ^= buf[p++];
00241             }
00242         }
00243 
00244         if ((((parity_bits >> 4) ^ parity_bits) & 0xF) != 0xF) {
00245             av_log(avctx, AV_LOG_INFO, "mlpparse: Parity check failed.\n");
00246             goto lost_sync;
00247         }
00248     } else {
00249         GetBitContext gb;
00250         MLPHeaderInfo mh;
00251 
00252         init_get_bits(&gb, buf + 4, (buf_size - 4) << 3);
00253         if (ff_mlp_read_major_sync(avctx, &mh, &gb) < 0)
00254             goto lost_sync;
00255 
00256         avctx->bits_per_raw_sample = mh.group1_bits;
00257         if (avctx->bits_per_raw_sample > 16)
00258             avctx->sample_fmt = SAMPLE_FMT_S32;
00259         else
00260             avctx->sample_fmt = SAMPLE_FMT_S16;
00261         avctx->sample_rate = mh.group1_samplerate;
00262         avctx->frame_size = mh.access_unit_size;
00263 
00264         if (mh.stream_type == 0xbb) {
00265             /* MLP stream */
00266             avctx->channels = mlp_channels[mh.channels_mlp];
00267         } else { /* mh.stream_type == 0xba */
00268             /* TrueHD stream */
00269             if (mh.channels_thd_stream2)
00270                 avctx->channels = truehd_channels(mh.channels_thd_stream2);
00271             else
00272                 avctx->channels = truehd_channels(mh.channels_thd_stream1);
00273         }
00274 
00275         if (!mh.is_vbr) /* Stream is CBR */
00276             avctx->bit_rate = mh.peak_bitrate;
00277 
00278         mp->num_substreams = mh.num_substreams;
00279     }
00280 
00281     *poutbuf = buf;
00282     *poutbuf_size = buf_size;
00283 
00284     return next;
00285 
00286 lost_sync:
00287     mp->in_sync = 0;
00288     return 1;
00289 }
00290 
00291 AVCodecParser mlp_parser = {
00292     { CODEC_ID_MLP, CODEC_ID_TRUEHD },
00293     sizeof(MLPParseContext),
00294     mlp_init,
00295     mlp_parse,
00296     ff_parse_close,
00297 };

Generated on Fri Sep 16 2011 17:17:39 for FFmpeg by  doxygen 1.7.1