Logo Search packages:      
Sourcecode: vdr-plugin-bitstreamout version File versions  Download package

mp2.c

/*
 * mp2.c:   Use the S/P-DIF interface for redirecting MP2 stream
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
 *
 * Copyright (C) 2003-2005 Werner Fink, <werner@suse.de>
 * Copyright (C) 2003 Sven Goethel, <sven@jausoft.com>
 */

#include <netinet/in.h>
#include <vdr/thread.h>
#include "types.h"
#include "mp2.h"
#include "shm_memory_tool.h"

#define USE_LAST_FRAME        1     // In case of CRC error

//#define DEBUG_MP2
#ifdef  DEBUG_MP2
# define debug_mp2(args...) fprintf(stderr, args)
#else
# define debug_mp2(args...)
#endif

// --- cMP2 : Scanning MP2 stream for counting and decoding into PCM frames ------------

cMP2 mp2(48000);

const uint_32 cMP2::samplerate_table[3] = {44100, 48000, 32000};
const uint_32 cMP2::bitrate_table[5][15] = {
    // MPEG-1
    {0,  32000,  64000,  96000, 128000, 160000, 192000, 224000,
      256000, 288000, 320000, 352000, 384000, 416000, 448000 }, // Layer I
    {0,  32000,  48000,  56000,  64000,  80000,  96000, 112000,
      128000, 160000, 192000, 224000, 256000, 320000, 384000 }, // Layer II
    {0,  32000,  40000,  48000,  56000,  64000,  80000,  96000,
      112000, 128000, 160000, 192000, 224000, 256000, 320000 }, // Layer III
    // MPEG-2 LSF
    {0,  32000,  48000,  56000,  64000,  80000,  96000, 112000,
      128000, 144000, 160000, 176000, 192000, 224000, 256000 }, // Layer I
    {0,   8000,  16000,  24000,  32000,  40000,  48000,  56000,
       64000,  80000,  96000, 112000, 128000, 144000, 160000 }  // Layer II&III
};
const uint_16 cMP2::magic = 0xffe0;

cMP2::cMP2(unsigned int rate)
#ifndef MP2_BURST_SIZE
: iec60958(rate, SPDIF_BURST_SIZE, 0)           // 32ms max buffer
#else
: iec60958(rate, MP2_BURST_SIZE, 0)       // 24ms buffer
#endif
 , running(false)
{
    reset_scan();
    reset_count();
}

cMP2::~cMP2(void)
{
    Release();
}

inline void cMP2::parse_syncinfo(mp2info_t &syncinfo, const uint_8 *data)
{
    uint_32 bit_rate;
    int index;
    uint_8 padding;

    syncinfo.frame_size = 0;

    syncinfo.ext   = ((data[1] & 0x10) >> 4) == 0;
    syncinfo.lsf   = ((data[1] & 0x08) >> 3) == 0;
    syncinfo.layer = 4 - ((data[1] & 0x06) >> 1);

    if ((syncinfo.layer == 4) || (!syncinfo.lsf && syncinfo.ext))
      return;

    if ((index = (data[2] & 0x0c)) == 0x0c)
      return;
    index >>= 2;

    syncinfo.sampling_rate = samplerate_table[index];
    if (syncinfo.lsf) {
      syncinfo.sampling_rate /= 2;
      if (syncinfo.ext)
          syncinfo.sampling_rate /= 2;
    }

    if ((index = (data[2] & 0xf0)) == 0xf0)
      return;
    index >>= 4;

    if (syncinfo.lsf)
      bit_rate = bitrate_table[3 + (syncinfo.layer >> 1)][index];
    else
      bit_rate = bitrate_table[syncinfo.layer - 1][index];

    padding = (data[2] & 0x02) >> 1;

    if (syncinfo.layer == 1) {
      syncinfo.frame_size = 4*((12 * bit_rate / syncinfo.sampling_rate) + padding);
      syncinfo.burst_size = 1536;
    } else {
      const uint_16 slots = ((syncinfo.layer == 3) && syncinfo.lsf) ? 72 : 144;
      syncinfo.frame_size = (slots * bit_rate / syncinfo.sampling_rate) + padding;
      syncinfo.burst_size = 32 * slots;
    }
}

inline mad_fixed_t cMP2::Prng(const mad_fixed_t state)
{
    return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
}

sint_32 cMP2::Dither(mad_fixed_t sample, dither_t &dither)
{
    const uint_32 scalebits = MAD_F_FRACBITS + 1 - SAMPLE_DEPTH;
    const mad_fixed_t mask = (1L << scalebits) - 1;
    mad_fixed_t output, random;

    sample += dither.error[0] - dither.error[1] + dither.error[2];

    dither.error[2] = dither.error[1];
    dither.error[1] = dither.error[0] >> 1;

    // bias
    output = sample + (1L << (scalebits - 1));

    // dither
    random  = Prng(dither.random);
    output += (random & mask) - (dither.random & mask);

    dither.random = random;

    // clip
    if (output > MAX_SPL) {
      output = MAX_SPL;
      if (sample > MAX_SPL)
          sample = MAX_SPL;
    } else if (output < MIN_SPL) {
      output = MIN_SPL;
      if (sample < MIN_SPL)
          sample = MIN_SPL;
    }

    // quantize
    output &= ~mask;

    // error feedback
    dither.error[0] = sample - output;

    // scale
    return output >> scalebits;
}

sint_32 cMP2::Round(mad_fixed_t sample, dither_t &dither)
{
    const uint_32 scalebits = MAD_F_FRACBITS + 1 - SAMPLE_DEPTH;

    // round
    sample += (1L << (scalebits - 1));

    // clip
    if (sample > MAX_SPL)
      sample = MAX_SPL;
    else if (sample < MIN_SPL)
      sample = MIN_SPL;

    // scale
    return sample >> scalebits;
}

inline ssize_t cMP2::Sample(uint_8 *data, size_t cnt)
{
    ssize_t len = B2F(cnt);
    struct mad_pcm *pcm;

    mad_synth_frame(&synth, &frame);
    pcm = &synth.pcm;

    if (pcm->channels > 2) {
      esyslog("MP2PCM: ** Invalid channel number found - try to syncing **");
      goto fail;
    }

    if (pcm->samplerate != sample_rate) {
      esyslog("MP2PCM: ** Invalid sample rate found - try to syncing **");
      goto fail;
    }

    if (len > pcm->length)
      len = pcm->length;

#if !defined(_GNU_SOURCE)
# define pcm_cast(a)     (unsigned char)((a) & 0xff)
    if (pcm->channels > 1) {
      const mad_fixed_t * left  = pcm->samples[0];
      const mad_fixed_t * right = pcm->samples[1];
      const uint_8 *end = data + F2B(len);

      while (data < end) {
          sint_32 sample;
          sample = Scale(*left++,  dith[0]);
# ifndef WORDS_BIGENDIAN
          *data++ = pcm_cast(sample >> 0);
          *data++ = pcm_cast(sample >> 8);
# else
          *data++ = pcm_cast(sample >> 8);
          *data++ = pcm_cast(sample >> 0);
# endif
          sample = Scale(*right++, dith[1]);
# ifndef WORDS_BIGENDIAN
          *data++ = pcm_cast(sample >> 0);
          *data++ = pcm_cast(sample >> 8);
# else
          *data++ = pcm_cast(sample >> 8);
          *data++ = pcm_cast(sample >> 0);
# endif
      }
    } else {
      const mad_fixed_t * left  = pcm->samples[0];
      const uint_8 *end = data + F2B(len);

      while (data < end) {
          sint_32 sample = Scale(*left++,  dith[0]);
# ifndef WORDS_BIGENDIAN
          *data++ = pcm_cast(sample >> 0);
          *data++ = pcm_cast(sample >> 8);
          *data++ = pcm_cast(sample >> 0);
          *data++ = pcm_cast(sample >> 8);
# else
          *data++ = pcm_cast(sample >> 8);
          *data++ = pcm_cast(sample >> 0);
          *data++ = pcm_cast(sample >> 8);
          *data++ = pcm_cast(sample >> 0);
# endif
      }
    }

#else // if defined(_GNU_SOURCE)
# define pcm_cast(a)     (unsigned short)((a) & 0xffff)
    if (pcm->channels > 1) {
      const mad_fixed_t * left  = pcm->samples[0];
      const mad_fixed_t * right = pcm->samples[1];
      uint_16 *to = (uint_16 *)data;
      const uint_16 *end = to + (len << 1);

      while (to < end) {
          sint_32 sample;
          sample = Scale(*left++,  dith[0]);
          *to++ = pcm_cast(sample);

          sample = Scale(*right++, dith[1]);
          *to++ = pcm_cast(sample);
      }

    } else {
      const mad_fixed_t * left  = pcm->samples[0];
      uint_16 *to = (uint_16 *)data;
      const uint_16 *end = to + (len << 1);

      while (to < end) {
          sint_32 sample = Scale(*left++,  dith[0]);
          *to++ = pcm_cast(sample);
          *to++ = pcm_cast(sample);
      }
    }
#endif
#undef pcm_cast

    return F2B(len);
fail:
    return -1;
}

inline bool cMP2::BufferGuard(void)
{
    bool ret = true;

    if (!stream.next_frame)
      goto out;

    if ((stream.bufend - stream.next_frame) == MAD_BUFFER_GUARD)
      goto out;

    ret = false;

out:
    return ret;
}

size_t cMP2::Stream(uint_8 *data, size_t cnt)
{
    size_t todo = MP2_BUFFER_SIZE;

    if (!running) Start();

    if (!BufferGuard()) {
      //
      // We always start with a buffer which starts its self with
      // the mp2 audio sync word and with MAD_BUFFER_GUARD bytes
      // of the next mp2 frame appended to the current mp2 frame.
      // This requires that the previous rest is also of the size
      // of MAD_BUFFER_GUARD or simply zero at start.
      //
      esyslog("MP2PCM: ** Invalid rest found - try to syncing **");
      return 0;
    }

    if (cnt > todo) {
      esyslog("MP2PCM: ** Invalid frame size - try to syncing **");
      return 0;
    }

    if (todo > cnt) todo = cnt;

    mad_stream_buffer(&stream, data, todo);
    stream.error = MAD_ERROR_NONE;

    return todo;
}

int cMP2::Decode(void)
{
    int todo = MP2_DATA;

    if (!stream.buffer || stream.error == MAD_ERROR_BUFLEN)
      goto out;

    todo = MP2_PLAY;                // We can play
    if (mad_frame_decode(&frame, &stream) == 0)
      goto out;
    if (stream.error == MAD_ERROR_NONE)
      goto out;

    todo = MP2_DATA;                // We need more data
    if (stream.error == MAD_ERROR_BUFLEN)
      goto out;

    todo = MP2_ERROR;               // Restart decoder
    if (!MAD_RECOVERABLE(stream.error))
      goto out;

    todo = MP2_LAST;                // Repeat last frame
    mad_stream_skip(&stream, stream.next_frame - stream.this_frame);
out:
    return todo;
}

void cMP2::Start(void)
{
    if (test_flags(MP2SPDIF)) {
      Offset(8);              // We use an IEC60958 PCM head
      return;
    }
    if (running) Stop();
    Offset(0);
    Scale = (test_flags(MP2DITHER)) ? Dither : Round;
    reset_scan();
    mad_stream_init(&stream);
    mad_stream_options(&stream, (MAD_OPTION_IGNORECRC));
    mad_frame_init (&frame);
    mad_header_init(&frame.header);
    mad_synth_init (&synth);
    memset(&dith[0], 0, sizeof(dither_t));
    memset(&dith[1], 0, sizeof(dither_t));
    running = true;
}

void cMP2::Stop (void)
{
    mad_synth_finish (&synth);
    mad_frame_finish (&frame);
    mad_stream_finish(&stream);
    reset_scan();
    running = false;
    if (test_flags(MP2SPDIF))
      Offset(8);              // We use an IEC60958 PCM head
}

const bool cMP2::Initialize(void)
{
    uint_8 * ptr = (uint_8 *)shm_malloc(MP2_BUFFER_SIZE + MAD_BUFFER_GUARD);
    if (!ptr)
      return false;
    ctr.Lock();
    nextin = ptr;
    currin = ptr + MAD_BUFFER_GUARD;
    ctr.Unlock();
    return true;
}

const void cMP2::Release(void)
{
    uint_8 * ptr = nextin;
    if (running) Stop();
    ctr.Lock();
    currin = nextin = (uint_8*)0;
    ctr.Unlock();
    shm_free(ptr);
}

// This function requires two arguments:
//   first is the start of the data segment
//   second is the tail of the data segment
const frame_t & cMP2::Frame(const uint_8 *&out, const uint_8 *const tail)
{
    play.burst = (uint_32 *)0;
    play.size  = 0;

    ctr.Lock();
    if (!currin) goto done;
newsync:
    //
    // Scan the old buffer first which was remembered in
    // the nextin buffer during the last scan at the end.
    //
    if (s.buffer_gard == MAD_BUFFER_GUARD) {
      //
      // Only used if libmad decodes MP2 data frames because
      // all of this frames had to be appended with the next
      // MAD_BUFFER_GUARD bytes of the following MP2 frame.
      //
#if !defined(MAD_BUFFER_GUARD) || (MAD_BUFFER_GUARD < 3)
# error Value of MAD_BUFFER_GUARD seems to be broken
#endif
      const uint_8 * obuf       = &nextin[0];               // Old buffer
      const uint_8 * const tbuf = obuf + s.buffer_gard;     // Tail of old buffer
      s.buffer_gard = 0;                              // No guard bytes anymore

    seek:
      //
      // Find the mp2 audio sync word
      //
      while((s.syncword & magic) != magic) {
          if (obuf >= tbuf)
            goto resync;
          s.syncword = (s.syncword << 8) | *obuf++;
      }

      //
      // If we've our magic syncword we should
      // remember it in our current input buffer
      //
      ((uint_16*)&currin[0])[0] = ntohs(s.syncword);

      //
      // Need the next 3 bytes to decide how big
      // and which mode the frame is
      //
      while(s.pos < 3) {
          if (obuf >= tbuf)
            goto resync;
          currin[s.pos++] = *obuf++;
      }

      //
      // Parse and check syncinfo if not known for this frame
      //
      parse_syncinfo(s.syncinfo, currin);
      if (!s.syncinfo.frame_size) {
          s.syncword = 0x001f;
          s.pos = 2;
          esyslog("MP2PCM: ** Invalid frame found - try to syncing **");
          if (obuf >= tbuf)
            goto resync;
          else
            goto seek;
      }
      s.payload_size = s.syncinfo.frame_size;

      //
      // Maybe: Reinit spdif interface if sample rate is changed
      //
      if (s.syncinfo.sampling_rate != sample_rate) {
          s.syncword = 0x001f;
          s.pos = 2;
          s.payload_size = 0;
          esyslog("MP2PCM: ** Invalid sample rate found - try to syncing **");
          if (obuf >= tbuf)
            goto resync;
          else
            goto seek;
      }

      while(s.pos < s.payload_size) {
          int rest = tbuf - obuf;
          if (rest <= 0)
            goto resync;
          if (rest + s.pos > s.payload_size)
            rest = s.payload_size - s.pos;
          memcpy(&currin[s.pos], obuf, rest);
          s.pos += rest;
          obuf  += rest;
      }

    } // if (s.buffer_gard == MAD_BUFFER_GUARD)

resync:
    //
    // Find the mp2 audio sync word
    //
    while((s.syncword & magic) != magic) {
      if (out >= tail)
          goto done;
      s.syncword = (s.syncword << 8) | *out++;
    }

    //
    // If we've our magic syncword we should
    // remember it in our current input buffer
    //
    if (s.pos == 2)
      ((uint_16*)&currin[0])[0] = ntohs(s.syncword);

    //
    // Need the next 3 bytes to decide how big
    // and which mode the frame is
    //
    while(s.pos < 3) {
      if (out >= tail)
          goto done;
      currin[s.pos++] = *out++;
    }

    //
    // Parse and check syncinfo if not known for this frame
    //
    if (!s.payload_size) {
      parse_syncinfo(s.syncinfo, currin);
      if (!s.syncinfo.frame_size) {
          s.syncword = 0x001f;
          s.pos = 2;
          esyslog("MP2PCM: ** Invalid frame found - try to syncing **");
          if (out >= tail)
            goto done;
          else
            goto resync;
      }
      s.payload_size = s.syncinfo.frame_size;
    }

    //
    // Maybe: Reinit spdif interface if sample rate is changed
    //
    if (s.syncinfo.sampling_rate != sample_rate) {
      s.syncword = 0x001f;
      s.pos = 2;
      s.payload_size = 0;
      esyslog("MP2PCM: ** Invalid sample rate found - try to syncing **");
      if (out >= tail)
          goto done;
      else
          goto resync;
    }

    while(s.pos < s.payload_size) {
      int rest = tail - out;
      if (rest <= 0)
          goto done;
      if (rest + s.pos > s.payload_size)
          rest = s.payload_size - s.pos;
      memcpy(&currin[s.pos], out, rest);
      s.pos += rest;
      out   += rest;
    }

    if (test_flags(MP2SPDIF)) {
      //
      // If we reach this point, we found a valid AC3 frame to warp into PCM (IEC60958)
      // accordingly to IEC61937
      //
      // What | PCM head              | MP2   payload
      // pos  | 0,1 | 2,3 | 4,5 | 6,7 | 8,9 |
      // size |  16 |  16 |  16 |  16 |  16 |
      // pos  |                       | 0,1 |
      //
      pcm[0] = char2short(0xf8, 0x72);                      // Pa
      pcm[1] = char2short(0x4e, 0x1f);                      // Pb
      pcm[2] = char2short(0x00, (s.syncinfo.layer == 1) ? 4 : 5); // Mp2 data
      pcm[3] = shorts((s.syncinfo.frame_size * 8));               // Frame size in bits

      swab(currin, payload, s.payload_size);
      memset(payload + s.payload_size, 0,  s.syncinfo.burst_size - 8 - s.payload_size);

      play.burst = (uint_32 *)(&current[0]);
      play.size  = s.syncinfo.burst_size;
      play.pay   = s.payload_size;

    } else {

      //
      // Libmad decodes MP2 data frames only if the next MAD_BUFFER_GUARD bytes
      // of the following MP2 frame are appended to the input buffer.  Remember
      // this few bytes to be scanned first on next scan.
      //
      while(s.buffer_gard < MAD_BUFFER_GUARD) {
          int rest = tail - out;
          if (rest <= 0)
            goto done;
          if (rest + s.buffer_gard > MAD_BUFFER_GUARD)
            rest = MAD_BUFFER_GUARD - s.buffer_gard;

          memcpy(&nextin[s.buffer_gard],   out, rest);      // Head of next buffer
          memcpy(&currin[s.pos+s.buffer_gard], out, rest);  // Tail of current buffer
          s.buffer_gard += rest;
          out             += rest;
      }

      if (Stream(currin, s.payload_size + s.buffer_gard) == 0) {
          s.syncword = 0x001f;                        // Error during streaming
          s.pos = 2;
          s.sample_size = 0;
          s.payload_size = 0;
          if (out >= tail)
            goto done;
          else
            goto newsync;                             // No goto resync due buffer_gard
      }

      int status = MP2_PLAY;
      do {
          if ((status = Decode()) != MP2_PLAY)
            break;

          s.sample_size = Sample(&current[0], MP2_BURST_SIZE - s.sample_size);

          if (BufferGuard())                          // Do we cross buffer guard line?
            break;

      } while (status == MP2_PLAY);

      switch (status) {
      case MP2_LAST:
          s.syncword = 0x001f;
          s.pos = 2;
          s.sample_size = 0;
          s.payload_size = 0;
#ifdef USE_LAST_FRAME
          dsyslog("MP2PCM: ** mad library failed - repeat last frame **");
          play.burst = last.burst;
          play.size  = last.size;
          play.pay   = last.pay;
          goto done;
#else
          dsyslog("MP2PCM: ** mad library failed - try to syncing **");
          if (out >= tail)
            goto done;
          else
            goto newsync;                             // No goto resync due buffer_gard
#endif
      case MP2_ERROR:
          s.syncword = 0x001f;
          s.pos = 2;
          s.sample_size = 0;
          s.payload_size = 0;
          esyslog("MP2PCM: ** Error in mad library - try to restart **");
          if (out >= tail)
            goto done;
          else
            goto newsync;                             // No goto resync due buffer_gard
      default:
          break;
      }

      play.burst = (uint_32 *)(&current[0]);
      play.size  = s.sample_size;
      play.pay   = s.sample_size;
    }

    Switch();

    last.burst = (uint_32 *)(&remember[0]);
    last.size  = play.size;
    last.pay   = play.pay;

    s.syncword = 0x001f;
    s.pos = 2;
    s.sample_size = 0;
    s.payload_size = 0;
done:
    ctr.Unlock();
    return play;
}

const bool cMP2::Count(const uint_8 *buf, const uint_8 *const tail)
{
    bool ret = false;

resync:
    if (c.bfound < 3) {
      switch(c.bfound) {
      case 0 ... 1:
          while((c.syncword & magic) != magic) {
            if (buf >= tail)
                goto out;
            c.syncword = (c.syncword << 8) | *buf++;
          }

          if (c.buffer_gard && (c.buffer_gard == MAD_BUFFER_GUARD))
            c.buffer_gard -= 2;
          else
            c.buffer_gard = 0;

          c.sync.ext   = ((c.syncword & 0x0010) >> 4) == 0;
          c.sync.lsf   = ((c.syncword & 0x0008) >> 3) == 0;
          c.sync.layer = 4 - ((c.syncword & 0x0006) >> 1);

          // Sanity check for mpeg audio
          if ((c.sync.layer == 4) || (!c.sync.lsf && c.sync.ext)) {     // Combination
            c.bfound = 0;
            c.syncword = 0x001f;
            memset(&c.sync, 0, sizeof(mp2info_t));
            goto resync;                              // ... not valid
          }

          c.bfound = 2;
      case 2:
          if (buf >= tail)
            goto out;
          {                                     // Frame size calculation
            uint_32 bit_rate;
            int index;
            uint_8 padding;

            if (c.buffer_gard && (c.buffer_gard == MAD_BUFFER_GUARD - 2))
                 c.buffer_gard--;
            else
                 c.buffer_gard = 0;

            if ((index = ((*buf) & 0x0c)) == 0x0c) {  // Sample rate index
                c.bfound = 0;
                c.syncword = 0x001f;
                memset(&c.sync, 0, sizeof(mp2info_t));
                goto resync;                    // ... not valid
            }
            index >>= 2;

            c.sync.sampling_rate = samplerate_table[index];
            if (c.sync.lsf) {                   // Sample rate
                c.sync.sampling_rate /= 2;
                if (c.sync.ext)
                  c.sync.sampling_rate /= 2;
            }

            if ((index = ((*buf) & 0xf0)) == 0xf0) {  // Bit rate index
                c.bfound = 0;
                c.syncword = 0x001f;
                memset(&c.sync, 0, sizeof(mp2info_t));
                goto resync;                    // ... not valid
            }
            index >>= 4;

            if (c.sync.lsf)
                bit_rate = bitrate_table[3 + (c.sync.layer >> 1)][index];
            else
                bit_rate = bitrate_table[c.sync.layer - 1][index];

            padding = ((*buf) & 0x02) >> 1;

            if (c.sync.layer == 1) {
                c.fsize = 4*((12 * bit_rate / c.sync.sampling_rate) + padding);
            } else {
                const uint_16 slots = ((c.sync.layer == 3) && c.sync.lsf) ? 72 : 144;
                c.fsize = (slots * bit_rate / c.sync.sampling_rate) + padding;
            }
          }
          debug_mp2("count_mp2_frame: %d %d\n", c.sync.layer, c.fsize);
          buf++;
          c.bfound++;
      default:
          break;
      }
    }

    while (c.bfound < c.fsize) {
      int skip, pay;
      if ((skip = tail - buf) <= 0)
          goto out;
      if (skip > (pay = c.fsize - c.bfound))
          skip = pay;
      c.bfound += skip;
      buf    += skip;

      if (c.buffer_gard) {                      // Decrease also buffer guard
          if (skip > c.buffer_gard)
            skip = c.buffer_gard;
          if ((c.buffer_gard -= skip) == 0)           // ... here and maybe we have
            ret = true;                   // crossed a frame and the guard
      }
    }

    if (c.fsize && (c.bfound >= c.fsize)) {
      c.bfound = 0;
      c.syncword = 0x001f;
      memset(&c.sync, 0, sizeof(mp2info_t));
      debug_mp2("count_mp2_frame: frame crossed\n");
      if (test_flags(MP2SPDIF))
          ret = true;
      else
          c.buffer_gard = MAD_BUFFER_GUARD;           // We have to await the buffer guard
      if (buf >= tail)
          goto out;
      goto resync;
    }
out:
    return ret;
}

Generated by  Doxygen 1.6.0   Back to index