Exemple #1
0
static PyObject * py_ogg_ogg_page_pageno(PyObject *self, PyObject *args) {
  int size;
  long c_out;
  ogg_page * og;
  PyArg_ParseTuple(args, "s#", &og, &size);
  c_out = ogg_page_pageno(og);
  return Py_BuildValue("l", c_out);
};
Exemple #2
0
void CAOggFLACDecoder::InPacket(const void* inInputData, const AudioStreamPacketDescription* inPacketDescription)
{
    if (!mCompressionInitialized)
        CODEC_THROW(kAudioCodecUnspecifiedError);

    ogg_page op;

    if (!WrapOggPage(&op, inInputData, inPacketDescription->mDataByteSize + inPacketDescription->mStartOffset, inPacketDescription->mStartOffset))
        CODEC_THROW(kAudioCodecUnspecifiedError);

    dbg_printf("[ oFD]   : [%08lx] InPacket() [%4.4s] %ld\n", (UInt32) this, (char *) (static_cast<const Byte*> (inInputData) + inPacketDescription->mStartOffset),
               ogg_page_pageno(&op));

    ogg_packet opk;
    SInt32 packet_count = 0;
    int oret;
    AudioStreamPacketDescription flac_packet_desc = {0, 0, 0};
    UInt32 page_packets = ogg_page_packets(&op);

    ogg_stream_pagein(&mO_st, &op);
    while ((oret = ogg_stream_packetout(&mO_st, &opk)) != 0) {
        if (oret < 0) {
            page_packets--;
            continue;
        }

        packet_count++;

        flac_packet_desc.mDataByteSize = opk.bytes;

        CAFLACDecoder::InPacket(opk.packet, &flac_packet_desc);
    }

    if (packet_count > 0)
        complete_pages += 1;

    mFramesBufferedList.push_back(OggPagePacket(packet_count, inPacketDescription->mVariableFramesInPacket));
}
Exemple #3
0
int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
  unsigned char *header=og->header;
  unsigned char *body=og->body;
  long           bodysize=og->body_len;
  int            segptr=0;

  int version=ogg_page_version(og);
  int continued=ogg_page_continued(og);
  int bos=ogg_page_bos(og);
  int eos=ogg_page_eos(og);
  ogg_int64_t granulepos=ogg_page_granulepos(og);
  int serialno=ogg_page_serialno(og);
  long pageno=ogg_page_pageno(og);
  int segments=header[26];
  
  /* clean up 'returned data' */
  {
    long lr=os->lacing_returned;
    long br=os->body_returned;

    /* body data */
    if(br){
      os->body_fill-=br;
      if(os->body_fill)
	memmove(os->body_data,os->body_data+br,os->body_fill);
      os->body_returned=0;
    }

    if(lr){
      /* segment table */
      if(os->lacing_fill-lr){
	memmove(os->lacing_vals,os->lacing_vals+lr,
		(os->lacing_fill-lr)*sizeof(*os->lacing_vals));
	memmove(os->granule_vals,os->granule_vals+lr,
		(os->lacing_fill-lr)*sizeof(*os->granule_vals));
      }
      os->lacing_fill-=lr;
      os->lacing_packet-=lr;
      os->lacing_returned=0;
    }
  }

  /* check the serial number */
  if(serialno!=os->serialno)return(-1);
  if(version>0)return(-1);

  _os_lacing_expand(os,segments+1);

  /* are we in sequence? */
  if(pageno!=os->pageno){
    int i;

    /* unroll previous partial packet (if any) */
    for(i=os->lacing_packet;i<os->lacing_fill;i++)
      os->body_fill-=os->lacing_vals[i]&0xff;
    os->lacing_fill=os->lacing_packet;

    /* make a note of dropped data in segment table */
    if(os->pageno!=-1){
      os->lacing_vals[os->lacing_fill++]=0x400;
      os->lacing_packet++;
    }

    /* are we a 'continued packet' page?  If so, we'll need to skip
       some segments */
    if(continued){
      bos=0;
      for(;segptr<segments;segptr++){
	int val=header[27+segptr];
	body+=val;
	bodysize-=val;
	if(val<255){
	  segptr++;
	  break;
	}
      }
    }
  }
  
  if(bodysize){
    _os_body_expand(os,bodysize);
    memcpy(os->body_data+os->body_fill,body,bodysize);
    os->body_fill+=bodysize;
  }

  {
    int saved=-1;
    while(segptr<segments){
      int val=header[27+segptr];
      os->lacing_vals[os->lacing_fill]=val;
      os->granule_vals[os->lacing_fill]=-1;
      
      if(bos){
	os->lacing_vals[os->lacing_fill]|=0x100;
	bos=0;
      }
      
      if(val<255)saved=os->lacing_fill;
      
      os->lacing_fill++;
      segptr++;
      
      if(val<255)os->lacing_packet=os->lacing_fill;
    }
  
    /* set the granulepos on the last granuleval of the last full packet */
    if(saved!=-1){
      os->granule_vals[saved]=granulepos;
    }

  }

  if(eos){
    os->e_o_s=1;
    if(os->lacing_fill>0)
      os->lacing_vals[os->lacing_fill-1]|=0x200;
  }

  os->pageno=pageno+1;

  return(0);
}
/* Reads in buffers, parses them, reframes into one-buffer-per-ogg-page, submits
 * pages to output pad.
 */
static GstFlowReturn
gst_ogg_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
{
  GstOggParse *ogg;
  GstFlowReturn result = GST_FLOW_OK;
  gint ret = -1;
  guint32 serialno;
  GstBuffer *pagebuffer;
  GstClockTime buffertimestamp = GST_BUFFER_TIMESTAMP (buffer);

  ogg = GST_OGG_PARSE (parent);

  GST_LOG_OBJECT (ogg,
      "Chain function received buffer of size %" G_GSIZE_FORMAT,
      gst_buffer_get_size (buffer));

  gst_ogg_parse_submit_buffer (ogg, buffer);

  while (ret != 0 && result == GST_FLOW_OK) {
    ogg_page page;

    /* We use ogg_sync_pageseek() rather than ogg_sync_pageout() so that we can
     * track how many bytes the ogg layer discarded (in the case of sync errors,
     * etc.); this allows us to accurately track the current stream offset
     */
    ret = ogg_sync_pageseek (&ogg->sync, &page);
    if (ret == 0) {
      /* need more data, that's fine... */
      break;
    } else if (ret < 0) {
      /* discontinuity; track how many bytes we skipped (-ret) */
      ogg->offset -= ret;
    } else {
      gint64 granule = ogg_page_granulepos (&page);
#ifndef GST_DISABLE_GST_DEBUG
      int bos = ogg_page_bos (&page);
#endif
      guint64 startoffset = ogg->offset;
      GstOggStream *stream;
      gboolean keyframe;

      serialno = ogg_page_serialno (&page);
      stream = gst_ogg_parse_find_stream (ogg, serialno);

      GST_LOG_OBJECT (ogg, "Timestamping outgoing buffer as %" GST_TIME_FORMAT,
          GST_TIME_ARGS (buffertimestamp));

      if (stream) {
        buffertimestamp = gst_ogg_stream_get_end_time_for_granulepos (stream,
            granule);
        if (ogg->video_stream) {
          if (stream == ogg->video_stream) {
            keyframe = gst_ogg_stream_granulepos_is_key_frame (stream, granule);
          } else {
            keyframe = FALSE;
          }
        } else {
          keyframe = TRUE;
        }
      } else {
        buffertimestamp = GST_CLOCK_TIME_NONE;
        keyframe = TRUE;
      }
      pagebuffer = gst_ogg_parse_buffer_from_page (&page, startoffset,
          buffertimestamp);

      /* We read out 'ret' bytes, so we set the next offset appropriately */
      ogg->offset += ret;

      GST_LOG_OBJECT (ogg,
          "processing ogg page (serial %08x, pageno %ld, "
          "granule pos %" G_GUINT64_FORMAT ", bos %d, offset %"
          G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT ") keyframe=%d",
          serialno, ogg_page_pageno (&page),
          granule, bos, startoffset, ogg->offset, keyframe);

      if (ogg_page_bos (&page)) {
        /* If we've seen this serialno before, this is technically an error,
         * we log this case but accept it - this one replaces the previous
         * stream with this serialno. We can do this since we're streaming, and
         * not supporting seeking...
         */
        GstOggStream *stream = gst_ogg_parse_find_stream (ogg, serialno);

        if (stream != NULL) {
          GST_LOG_OBJECT (ogg, "Incorrect stream; repeats serial number %08x "
              "at offset %" G_GINT64_FORMAT, serialno, ogg->offset);
        }

        if (ogg->last_page_not_bos) {
          GST_LOG_OBJECT (ogg, "Deleting all referenced streams, found a new "
              "chain starting with serial %u", serialno);
          gst_ogg_parse_delete_all_streams (ogg);
        }

        stream = gst_ogg_parse_new_stream (ogg, &page);

        ogg->last_page_not_bos = FALSE;

        gst_buffer_ref (pagebuffer);
        stream->headers = g_list_append (stream->headers, pagebuffer);

        if (!ogg->in_headers) {
          GST_LOG_OBJECT (ogg,
              "Found start of new chain at offset %" G_GUINT64_FORMAT,
              startoffset);
          ogg->in_headers = 1;
        }

        /* For now, we just keep the header buffer in the stream->headers list;
         * it actually gets output once we've collected the entire set
         */
      } else {
        /* Non-BOS page. Either: we're outside headers, and this isn't a 
         * header (normal data), outside headers and this is (error!), inside
         * headers, this is (append header), or inside headers and this isn't 
         * (we've found the end of headers; flush the lot!)
         *
         * Before that, we flag that the last page seen (this one) was not a 
         * BOS page; that way we know that when we next see a BOS page it's a
         * new chain, and we can flush all existing streams.
         */
        page_type type;
        GstOggStream *stream = gst_ogg_parse_find_stream (ogg, serialno);

        if (!stream) {
          GST_LOG_OBJECT (ogg,
              "Non-BOS page unexpectedly found at %" G_GINT64_FORMAT,
              ogg->offset);
          goto failure;
        }

        ogg->last_page_not_bos = TRUE;

        type = gst_ogg_parse_is_header (ogg, stream, &page);

        if (type == PAGE_PENDING && ogg->in_headers) {
          gst_buffer_ref (pagebuffer);

          stream->unknown_pages = g_list_append (stream->unknown_pages,
              pagebuffer);
        } else if (type == PAGE_HEADER) {
          if (!ogg->in_headers) {
            GST_LOG_OBJECT (ogg, "Header page unexpectedly found outside "
                "headers at offset %" G_GINT64_FORMAT, ogg->offset);
            goto failure;
          } else {
            /* Append the header to the buffer list, after any unknown previous
             * pages
             */
            stream->headers = g_list_concat (stream->headers,
                stream->unknown_pages);
            g_list_free (stream->unknown_pages);
            gst_buffer_ref (pagebuffer);
            stream->headers = g_list_append (stream->headers, pagebuffer);
          }
        } else {                /* PAGE_DATA, or PAGE_PENDING but outside headers */
          if (ogg->in_headers) {
            /* First non-header page... set caps, flush headers.
             *
             * First up, we build a single GValue list of all the pagebuffers
             * we're using for the headers, in order.
             * Then we set this on the caps structure. Then we can start pushing
             * buffers for the headers, and finally we send this non-header
             * page.
             */
            GstCaps *caps;
            GstStructure *structure;
            GValue array = { 0 };
            gint count = 0;
            gboolean found_pending_headers = FALSE;
            GSList *l;

            g_value_init (&array, GST_TYPE_ARRAY);

            for (l = ogg->oggstreams; l != NULL; l = l->next) {
              GstOggStream *stream = (GstOggStream *) l->data;

              if (g_list_length (stream->headers) == 0) {
                GST_LOG_OBJECT (ogg, "No primary header found for stream %08x",
                    stream->serialno);
                goto failure;
              }

              gst_ogg_parse_append_header (&array,
                  GST_BUFFER (stream->headers->data));
              count++;
            }

            for (l = ogg->oggstreams; l != NULL; l = l->next) {
              GstOggStream *stream = (GstOggStream *) l->data;
              GList *j;

              /* already appended the first header, now do headers 2-N */
              for (j = stream->headers->next; j != NULL; j = j->next) {
                gst_ogg_parse_append_header (&array, GST_BUFFER (j->data));
                count++;
              }
            }

            caps = gst_pad_query_caps (ogg->srcpad, NULL);
            caps = gst_caps_make_writable (caps);

            structure = gst_caps_get_structure (caps, 0);
            gst_structure_take_value (structure, "streamheader", &array);

            gst_pad_set_caps (ogg->srcpad, caps);

            if (ogg->caps)
              gst_caps_unref (ogg->caps);
            ogg->caps = caps;

            GST_LOG_OBJECT (ogg, "Set \"streamheader\" caps with %d buffers "
                "(one per page)", count);

            /* Now, we do the same thing, but push buffers... */
            for (l = ogg->oggstreams; l != NULL; l = l->next) {
              GstOggStream *stream = (GstOggStream *) l->data;
              GstBuffer *buf = GST_BUFFER (stream->headers->data);

              result = gst_pad_push (ogg->srcpad, buf);
              if (result != GST_FLOW_OK)
                return result;
            }
            for (l = ogg->oggstreams; l != NULL; l = l->next) {
              GstOggStream *stream = (GstOggStream *) l->data;
              GList *j;

              /* pushed the first one for each stream already, now do 2-N */
              for (j = stream->headers->next; j != NULL; j = j->next) {
                GstBuffer *buf = GST_BUFFER (j->data);

                result = gst_pad_push (ogg->srcpad, buf);
                if (result != GST_FLOW_OK)
                  return result;
              }
            }

            ogg->in_headers = 0;

            /* And finally the pending data pages */
            for (l = ogg->oggstreams; l != NULL; l = l->next) {
              GstOggStream *stream = (GstOggStream *) l->data;
              GList *k;

              if (stream->unknown_pages == NULL)
                continue;

              if (found_pending_headers) {
                GST_WARNING_OBJECT (ogg, "Incorrectly muxed headers found at "
                    "approximate offset %" G_GINT64_FORMAT, ogg->offset);
              }
              found_pending_headers = TRUE;

              GST_LOG_OBJECT (ogg, "Pushing %d pending pages after headers",
                  g_list_length (stream->unknown_pages) + 1);

              for (k = stream->unknown_pages; k != NULL; k = k->next) {
                GstBuffer *buf = GST_BUFFER (k->data);

                result = gst_pad_push (ogg->srcpad, buf);
                if (result != GST_FLOW_OK)
                  return result;
              }
              g_list_foreach (stream->unknown_pages,
                  (GFunc) gst_mini_object_unref, NULL);
              g_list_free (stream->unknown_pages);
              stream->unknown_pages = NULL;
            }
          }

          if (granule == -1) {
            stream->stored_buffers = g_list_append (stream->stored_buffers,
                pagebuffer);
          } else {
            while (stream->stored_buffers) {
              GstBuffer *buf = stream->stored_buffers->data;

              buf = gst_buffer_make_writable (buf);

              GST_BUFFER_TIMESTAMP (buf) = buffertimestamp;
              if (!keyframe) {
                GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
              } else {
                keyframe = FALSE;
              }

              result = gst_pad_push (ogg->srcpad, buf);
              if (result != GST_FLOW_OK)
                return result;

              stream->stored_buffers =
                  g_list_delete_link (stream->stored_buffers,
                  stream->stored_buffers);
            }

            pagebuffer = gst_buffer_make_writable (pagebuffer);
            if (!keyframe) {
              GST_BUFFER_FLAG_SET (pagebuffer, GST_BUFFER_FLAG_DELTA_UNIT);
            } else {
              keyframe = FALSE;
            }

            result = gst_pad_push (ogg->srcpad, pagebuffer);
            if (result != GST_FLOW_OK)
              return result;
          }
        }
      }
    }
  }

  return result;

failure:
  gst_pad_push_event (GST_PAD (ogg->srcpad), gst_event_new_eos ());
  return GST_FLOW_ERROR;
}
Exemple #5
0
int main () {
  ogg_sync_state   oy; /* sync and verify incoming physical bitstream */
  ogg_stream_state os; /* take physical pages, weld into a logical
                          stream of packets */
  ogg_page         og; /* one Ogg bitstream page. Vorbis packets are inside */
  ogg_packet       op; /* one raw packet of data for decode */

  struct stream *st = NULL;

  int r;
  char *buffer;
  int  bytes;
  int eos = 0;
  int i;
  int bufferSize = 4096;

  r = ogg_sync_init(&oy); /* Now we can read pages */
  assert(r == 0);

  while (1) { /* we repeat if the bitstream is chained */

    /* submit a 4k block to the libogg sync layer */
    buffer = ogg_sync_buffer(&oy, bufferSize);
    bytes = fread(buffer, 1, bufferSize, stdin);
    if (bytes == 0) {
      fprintf(stderr, "Got stdin EOF.\n");
      r = 0; break;
    }

    r = ogg_sync_wrote(&oy, bytes);
    assert(r == 0);

    /* Get the first page. */
    r = ogg_sync_pageout(&oy, &og);
    if (r == 0) {
      fprintf(stderr, "Need more data.\n");
      continue;
    } else if (r < 1) {
      /* have we simply run out of data?  If so, we're done. */
      if (bytes < bufferSize) break;

      /* error case.  Must not be Vorbis data */
      fprintf(stderr, "Input does not appear to be an Ogg bitstream.\n");
      r = 1; break;
    }
    assert(r == 1);

    /* Get the serial number and set up the rest of decode. */
    /* serialno first; use it to set up a logical stream */
    int serialno = ogg_page_serialno(&og);
    int packets = ogg_page_packets(&og);
    fprintf(stderr, "version: %d\n", ogg_page_version(&og));
    fprintf(stderr, "continued: %d\n", ogg_page_continued(&og));
    fprintf(stderr, "pageno: %ld\n", ogg_page_pageno(&og));
    fprintf(stderr, "serialno: %d\n", serialno);
    fprintf(stderr, "packets: %d\n", packets);
    fprintf(stderr, "granulepos: %lld\n", ogg_page_granulepos(&og));
    fprintf(stderr, "eos: %d\n", ogg_page_eos(&og));
    fprintf(stderr, "bos: %d\n", ogg_page_bos(&og));


    /* we need to get the correct "ogg_stream_state" struct based on the serialno */
    struct stream *s = st;
    while (1) {
      if (s == NULL) {
        fprintf(stderr, "creating struct stream for %d\n", serialno);
        s = malloc(sizeof(struct stream));
        s->next = NULL;
        s->serialno = serialno;
        ogg_stream_init(&s->os, serialno);
        if (st == NULL) {
          st = s;
        } else {
          /* have to set "s" to the last element of the "st" linked list */
          struct stream *t = st;
          while (1) {
            if (t->next == NULL) {
              t->next = s;
              break;
            } else {
              t = t->next;
            }
          }
        }
        break;
      }
      if (s->serialno == serialno) {
        break;
      }
      s = s->next;
    }
    assert(s->serialno == serialno);
    fprintf(stderr, "using struct stream %d\n", s->serialno);
    /* holy shit that sucked... */


    if (ogg_stream_pagein(&s->os, &og) < 0) {
      /* error; stream version mismatch perhaps */
      fprintf(stderr, "Error reading page of Ogg bitstream data.\n");
      r = 1; break;
    }

    /* iterate though the "packets" in the page */
    for (i=0; i<packets; i++) {
      fprintf(stderr, "  Reading packet %d.\n", i);
      r = ogg_stream_packetout(&s->os, &op);
      fprintf(stderr, "  Reading packet result %d.\n", r);
      if (r != 1) {
        /* no page? must not be vorbis */
        fprintf(stderr, "  Error reading packet.\n");
        r = 1; break;
      }

      /**
       * At this point, you'd pass the raw packet data to the vorbis decoder or
       * whatever your destination is....
       */
      fprintf(stderr, "    bytes: %ld\n", op.bytes);
      fprintf(stderr, "    b_o_s: %ld\n", op.b_o_s);
      fprintf(stderr, "    e_o_s: %ld\n", op.e_o_s);
      fprintf(stderr, "    granulepos: %lld\n", op.granulepos);
      fprintf(stderr, "    packetno: %lld\n", op.packetno);
    }

    fprintf(stderr, "\n");
  }

  /* OK, clean up the framer */
  ogg_sync_clear(&oy);

  fprintf(stderr,"\nDone.\n");
  return r;
}
Exemple #6
0
ComponentResult process_stream_page__speex(OggImportGlobals *globals, StreamInfo *si, ogg_page *opg)
{
    ComponentResult ret = noErr;
    int ovret = 0;
    Boolean loop = true;
    Boolean movie_changed = false;

    TimeValue movieTS = GetMovieTimeScale(globals->theMovie);
    TimeValue mediaTS = 0;
    TimeValue mediaTS_fl = 0.0;

    ogg_packet op;

    switch(si->si_speex.state) {
    case kSStateReadingComments:
    case kSStateReadingAdditionalHeaders:
        ogg_stream_pagein(&si->os, opg);
        break;
    default:
        break;
    }

    do {
        switch(si->si_speex.state) {
        case kSStateReadingComments:
            ovret = ogg_stream_packetout(&si->os, &op);
            if (ovret < 0) {
                loop = false;
                ret = invalidMedia;
            } else if (ovret < 1) {
                loop = false;
            } else {
                unsigned long atomhead[2] = { EndianU32_NtoB(op.bytes + sizeof(atomhead)), EndianU32_NtoB(kCookieTypeSpeexComments) };

                PtrAndHand(atomhead, si->soundDescExtension, sizeof(atomhead));
                PtrAndHand(op.packet, si->soundDescExtension, op.bytes);

                ret = CreateTrackAndMedia(globals, si, opg);
                if (ret != noErr) {
                    dbg_printf("??? -- CreateTrackAndMedia failed?: %ld\n", (long)ret);
                }

                unpack_vorbis_comments(&si->si_speex.vc, op.packet, op.bytes);
                /*err =*/ DecodeCommentsQT(globals, si, &si->si_speex.vc);
                //NotifyMovieChanged(globals);

                si->si_speex.state = kSStateReadingAdditionalHeaders;
            }

            break;

        case kSStateReadingAdditionalHeaders:
            if (si->si_speex.skipped_headers >= si->si_speex.header.extra_headers) {
                unsigned long endAtom[2] = { EndianU32_NtoB(sizeof(endAtom)), EndianU32_NtoB(kAudioTerminatorAtomType) };

                ret = PtrAndHand(endAtom, si->soundDescExtension, sizeof(endAtom));
                if (ret == noErr) {
                    ret = AddSoundDescriptionExtension((SoundDescriptionHandle) si->sampleDesc,
                                                       si->soundDescExtension, siDecompressionParams);
                    //dbg_printf("??? -- Adding extension: %ld\n", ret);
                } else {
                    //dbg_printf("??? -- Hmm, something went wrong: %ld\n", ret);
                }

                si->insertTime = 0;
                si->streamOffset = globals->currentGroupOffset;
                mediaTS = GetMediaTimeScale(si->theMedia);
                mediaTS_fl = (Float64) mediaTS;
                si->streamOffsetSamples = (TimeValue) (mediaTS_fl * globals->currentGroupOffsetSubSecond) -
                    ((globals->currentGroupOffset % movieTS) * mediaTS / movieTS);
                dbg_printf("---/  / streamOffset: [%ld, %ld], %lg\n", si->streamOffset, si->streamOffsetSamples, globals->currentGroupOffsetSubSecond);
                si->incompleteCompensation = 0;
                si->si_speex.state = kSStateReadingFirstPacket;

                loop = false; // ??!
                break;
            }

            ovret = ogg_stream_packetout(&si->os, &op);
            if (ovret < 0) {
                loop = false;
                ret = invalidMedia;
            } else if (ovret < 1) {
                loop = false;
            } else {
                // not much here so far, basically just skip the extra header packet
                unsigned long atomhead[2] = { EndianU32_NtoB(op.bytes + sizeof(atomhead)), EndianU32_NtoB(kCookieTypeSpeexExtraHeader) };
                PtrAndHand(atomhead, si->soundDescExtension, sizeof(atomhead));
                PtrAndHand(op.packet, si->soundDescExtension, op.bytes);

                si->si_speex.skipped_headers += 1;
            }

            break;

        case kSStateReadingFirstPacket:
            if (ogg_page_pageno(opg) > 2) {
                si->lastGranulePos = ogg_page_granulepos(opg);
                dbg_printf("----==< skipping: %llx, %lx\n", si->lastGranulePos, ogg_page_pageno(opg));
                loop = false;

                if (si->lastGranulePos < 0)
                    si->lastGranulePos = 0;
            }
            si->si_speex.state = kSStateReadingPackets;
            break;

        case kVStateReadingPackets:
            {
                ogg_int64_t pos       = ogg_page_granulepos(opg);
                int         len       = opg->header_len + opg->body_len;
                TimeValue   duration  = pos - si->lastGranulePos;
                short       smp_flags = 0;

                if (ogg_page_continued(opg) || si->incompleteCompensation != 0)
                    smp_flags |= mediaSampleNotSync;

                if (duration <= 0) {
                    duration = INCOMPLETE_PAGE_DURATION;
                    si->incompleteCompensation -= INCOMPLETE_PAGE_DURATION;
                } else if (si->incompleteCompensation != 0) {
                    duration += si->incompleteCompensation;
                    si->incompleteCompensation = 0;
                    if (duration <= 0) {
                        ret = badFileFormat;
                        loop = false;
                        break;
                    }
                }

                if (si->insertTime == 0 && si->streamOffsetSamples > 0) {
                    dbg_printf("   -   :++: increasing duration (%ld) by sampleOffset: %ld\n", duration, si->streamOffsetSamples);
                    duration += si->streamOffsetSamples;
                }

                ret = _store_sample_reference(si, &globals->dataOffset, len, duration, smp_flags);
                if (ret != noErr) {
                    loop = false;
                    break;
                }

                if (!globals->usingIdle) {
                    if (si->sample_refs_count >= kSSRefsInitial)
                        ret = _commit_srefs(globals, si, &movie_changed);
                }

                if (pos != -1)
                    si->lastGranulePos = pos;
            }
            loop = false;
            break;

        default:
            loop = false;
        }
    } while(loop);

    if (movie_changed)
        NotifyMovieChanged(globals, false);

    return ret;
};
Exemple #7
0
int scan_get_oggfileinfo(char *filename, MP3FILE *pmp3) {
    FILE *file = fopen(filename, "rb");
    ogg_sync_state sync;
    ogg_page page;
    stream_set *processors = create_stream_set();
    int gotpage = 0;
    ogg_int64_t written = 0;
    struct stat psb;

    if(!file) {
        DPRINTF(E_FATAL, L_SCAN,
		"Error opening input file \"%s\": %s\n", filename,
		strerror(errno));
        return -1;
    }

    DPRINTF(E_INF, L_SCAN, "Processing file \"%s\"...\n\n", filename);

    if (!stat(filename, &psb)) {
        pmp3->time_added = psb.st_mtime;
	if (psb.st_ctime < pmp3->time_added) {
            pmp3->time_added = psb.st_ctime;
        }
        pmp3->time_modified = psb.st_mtime;
    } else {
        DPRINTF(E_WARN, L_SCAN, "Error statting: %s\n", strerror(errno));
    }

    ogg_sync_init(&sync);

    while(get_next_page(file, &sync, &page, &written)) {
        stream_processor *p = find_stream_processor(processors, &page);
        gotpage = 1;

        if(!p) {
            DPRINTF(E_FATAL, L_SCAN, "Could not find a processor for stream, bailing\n");
            return -1;
        }

        if(p->isillegal && !p->shownillegal) {
            char *constraint;
            switch(p->constraint_violated) {
                case CONSTRAINT_PAGE_AFTER_EOS:
                    constraint = "Page found for stream after EOS flag";
                    break;
                case CONSTRAINT_MUXING_VIOLATED:
                    constraint = "Ogg muxing constraints violated, new "
                                   "stream before EOS of all previous streams";
                    break;
                default:
                    constraint = "Error unknown.";
            }

            DPRINTF(E_WARN, L_SCAN, 
		    "Warning: illegally placed page(s) for logical stream %d\n"
                   "This indicates a corrupt ogg file: %s.\n", 
                    p->num, constraint);
            p->shownillegal = 1;
            /* If it's a new stream, we want to continue processing this page
             * anyway to suppress additional spurious errors
             */
            if(!p->isnew)
                continue;
        }

        if(p->isnew) {
  	    DPRINTF(E_DBG, L_SCAN, "New logical stream (#%d, serial: %08x): type %s\n", 
	      p->num, p->serial, p->type);
            if(!p->start)
                DPRINTF(E_WARN, L_SCAN,
			"stream start flag not set on stream %d\n",
                        p->num);
        }
        else if(p->start)
            DPRINTF(E_WARN, L_SCAN, "stream start flag found in mid-stream "
                      "on stream %d\n", p->num);

        if(p->seqno++ != ogg_page_pageno(&page)) {
            if(!p->lostseq) 
                DPRINTF(E_WARN, L_SCAN,
			"sequence number gap in stream %d. Got page %ld "
			"when expecting page %ld. Indicates missing data.\n",
			p->num, ogg_page_pageno(&page), p->seqno - 1);
            p->seqno = ogg_page_pageno(&page);
            p->lostseq = 1;
        }
        else
            p->lostseq = 0;

        if(!p->isillegal) {
            p->process_page(p, &page, pmp3);

            if(p->end) {
                if(p->process_end)
                    p->process_end(p, pmp3);
                DPRINTF(E_DBG, L_SCAN, "Logical stream %d ended\n", p->num);
                p->isillegal = 1;
                p->constraint_violated = CONSTRAINT_PAGE_AFTER_EOS;
            }
        }
    }

    free_stream_set(processors);

    ogg_sync_clear(&sync);

    fclose(file);

    if(!gotpage) {
        DPRINTF(E_FATAL, L_SCAN, "No ogg data found in file \"%s\".\n"
                "Input probably not ogg.\n", filename);
        return -1;
    }

    return 0;
}
Exemple #8
0
static void process_file(char *filename) {
    FILE *file = fopen(filename, "rb");
    ogg_sync_state sync;
    ogg_page page;
    stream_set *processors = create_stream_set();
    int gotpage = 0;
    ogg_int64_t written = 0;

    if(!file) {
        error(_("Error opening input file \"%s\": %s\n"), filename,
                    strerror(errno));
        return;
    }

    printf(_("Processing file \"%s\"...\n\n"), filename);

    ogg_sync_init(&sync);

    while(get_next_page(file, &sync, &page, &written)) {
        stream_processor *p = find_stream_processor(processors, &page);
        gotpage = 1;

        if(!p) {
            error(_("Could not find a processor for stream, bailing\n"));
            return;
        }

        if(p->isillegal && !p->shownillegal) {
            char *constraint;
            switch(p->constraint_violated) {
                case CONSTRAINT_PAGE_AFTER_EOS:
                    constraint = _("Page found for stream after EOS flag");
                    break;
                case CONSTRAINT_MUXING_VIOLATED:
                    constraint = _("Ogg muxing constraints violated, new "
                                   "stream before EOS of all previous streams");
                    break;
                default:
                    constraint = _("Error unknown.");
            }

            warn(_("Warning: illegally placed page(s) for logical stream %d\n"
                   "This indicates a corrupt ogg file: %s.\n"), 
                    p->num, constraint);
            p->shownillegal = 1;
            /* If it's a new stream, we want to continue processing this page
             * anyway to suppress additional spurious errors
             */
            if(!p->isnew)
                continue;
        }

        if(p->isnew) {
            info(_("New logical stream (#%d, serial: %08x): type %s\n"), 
                    p->num, p->serial, p->type);
            if(!p->start)
                warn(_("Warning: stream start flag not set on stream %d\n"),
                        p->num);
        }
        else if(p->start)
            warn(_("Warning: stream start flag found in mid-stream "
                      "on stream %d\n"), p->num);

        if(p->seqno++ != ogg_page_pageno(&page)) {
            if(!p->lostseq) 
                warn(_("Warning: sequence number gap in stream %d. Got page "
                       "%ld when expecting page %ld. Indicates missing data.\n"
                       ), p->num, ogg_page_pageno(&page), p->seqno - 1);
            p->seqno = ogg_page_pageno(&page);
            p->lostseq = 1;
        }
        else
            p->lostseq = 0;

        if(!p->isillegal) {
            p->process_page(p, &page);

            if(p->end) {
                if(p->process_end)
                    p->process_end(p);
                info(_("Logical stream %d ended\n"), p->num);
                p->isillegal = 1;
                p->constraint_violated = CONSTRAINT_PAGE_AFTER_EOS;
            }
        }
    }

    if(!gotpage)
        error(_("Error: No ogg data found in file \"%s\".\n"
                "Input probably not ogg.\n"), filename);

    free_stream_set(processors);

    ogg_sync_clear(&sync);

    fclose(file);
}
Exemple #9
0
ComponentResult process_stream_page__flac(OggImportGlobals *globals, StreamInfo *si, ogg_page *opg)
{
    ComponentResult ret = noErr;
    int ovret = 0;
    Boolean loop = true;
    Boolean movie_changed = false;

    TimeValue movieTS = GetMovieTimeScale(globals->theMovie);
    TimeValue mediaTS = 0;
    TimeValue mediaTS_fl = 0.0;

    ogg_packet op;

    switch(si->si_flac.state) {
    case kFStateReadingComments:
    case kFStateReadingAdditionalMDBlocks:
        ogg_stream_pagein(&si->os, opg);
        break;
    default:
        break;
    }

    do {
        switch(si->si_flac.state) {
        case kFStateReadingComments:
            ovret = ogg_stream_packetout(&si->os, &op);
            if (ovret < 0) {
                loop = false;
                ret = invalidMedia;
            } else if (ovret < 1) {
                loop = false;
            } else {
                ret = CreateTrackAndMedia(globals, si, opg);
                if (ret != noErr) {
                    dbg_printf("??? -- CreateTrackAndMedia failed?: %ld\n", (long)ret);
                    loop = false;
                    break;
                }

                if (si->si_flac.metablocks == 0 && (*((unsigned char*) op.packet) == 0xff)) {
                    si->si_flac.metablocks = si->si_flac.skipped;
                    si->si_flac.state = kFStateReadingAdditionalMDBlocks;
                    break;
                }

                {
                    unsigned long atomhead[2] = { EndianU32_NtoB(op.bytes + sizeof(atomhead)), EndianU32_NtoB(kCookieTypeFLACMetadata) };

                    PtrAndHand(atomhead, si->soundDescExtension, sizeof(atomhead));
                    PtrAndHand(op.packet, si->soundDescExtension, op.bytes);
                }

                if (((* (char *) op.packet) & 0x7f) == 4) {
                    dbg_printf("!  > - flac_stream_page - mb: %ld, skipped: %ld, h: %02x\n", si->si_flac.metablocks, si->si_flac.skipped,
                               (*(char *) op.packet) & 0x7f);
                    unpack_vorbis_comments(&si->si_flac.vc, ((char *) op.packet) + 4, op.bytes - 4);
                    /*err =*/ DecodeCommentsQT(globals, si, &si->si_flac.vc);
                    //NotifyMovieChanged(globals);
                }

                si->si_flac.skipped += 1;
                si->si_flac.state = kFStateReadingAdditionalMDBlocks;
            }

            break;

        case kFStateReadingAdditionalMDBlocks:
            dbg_printf("! -- - flac_stream_page - mb: %ld, skipped: %ld\n", si->si_flac.metablocks, si->si_flac.skipped);
            if (si->si_flac.metablocks > 0 && si->si_flac.skipped >= si->si_flac.metablocks) {
                unsigned long endAtom[2] = { EndianU32_NtoB(sizeof(endAtom)), EndianU32_NtoB(kAudioTerminatorAtomType) };

                ret = PtrAndHand(endAtom, si->soundDescExtension, sizeof(endAtom));
                if (ret == noErr) {
                    ret = AddSoundDescriptionExtension((SoundDescriptionHandle) si->sampleDesc,
                                                       si->soundDescExtension, siDecompressionParams);
                    //dbg_printf("??? -- Adding extension: %ld\n", ret);
                } else {
                    //dbg_printf("??? -- Hmm, something went wrong: %ld\n", ret);
                }

                si->insertTime = 0;
                si->streamOffset = globals->currentGroupOffset;
                mediaTS = GetMediaTimeScale(si->theMedia);
                mediaTS_fl = (Float64) mediaTS;
                si->streamOffsetSamples = (TimeValue) (mediaTS_fl * globals->currentGroupOffsetSubSecond) -
                    ((globals->currentGroupOffset % movieTS) * mediaTS / movieTS);
                dbg_printf("---/  / streamOffset: [%ld, %ld], %lg\n", si->streamOffset, si->streamOffsetSamples, globals->currentGroupOffsetSubSecond);
                si->incompleteCompensation = 0;
                si->si_flac.state = kFStateReadingFirstPacket;

                loop = false; // the audio data is supposed to start on a fresh page
                break;
            }

            ovret = ogg_stream_packetout(&si->os, &op);
            dbg_printf("! -- - flac_stream_page - ovret: %d\n", ovret);
            if (ovret < 0) {
                loop = false;
                ret = invalidMedia;
            } else if (ovret < 1) {
                loop = false;
            } else {
                // not much here so far, basically just skip the extra header packet
                unsigned long atomhead[2] = { EndianU32_NtoB(op.bytes + sizeof(atomhead)), EndianU32_NtoB(kCookieTypeFLACMetadata) };

                if (si->si_flac.metablocks == 0 && (* (unsigned char*) op.packet) == 0xff) {
                    si->si_flac.metablocks = si->si_flac.skipped;
                    break;
                }

                PtrAndHand(atomhead, si->soundDescExtension, sizeof(atomhead));
                PtrAndHand(op.packet, si->soundDescExtension, op.bytes);

                if (((* (unsigned char *) op.packet) & 0x7f) == 4) {
                    dbg_printf("!  > - flac_stream_page - mb: %ld, skipped: %ld, h: %02x\n", si->si_flac.metablocks, si->si_flac.skipped,
                               (*(char *) op.packet) & 0x7f);
                    unpack_vorbis_comments(&si->si_flac.vc, ((char *) op.packet) + 4, op.bytes - 4);
                    /*err =*/ DecodeCommentsQT(globals, si, &si->si_flac.vc);
                    //NotifyMovieChanged(globals);
                }

                si->si_flac.skipped += 1;
            }

            break;

        case kFStateReadingFirstPacket:
            // what to do with this one? is it needed at all??
            if (ogg_page_pageno(opg) > 2 && false) {
                si->lastGranulePos = ogg_page_granulepos(opg);
                dbg_printf("----==< skipping: %llx, %lx\n", si->lastGranulePos, ogg_page_pageno(opg));
                loop = false;

                if (si->lastGranulePos < 0)
                    si->lastGranulePos = 0;
            }
            si->si_flac.state = kFStateReadingPackets;
            break;

        case kFStateReadingPackets:
            {
                ogg_int64_t pos       = ogg_page_granulepos(opg);
                int         len       = opg->header_len + opg->body_len;
                TimeValue   duration  = pos - si->lastGranulePos;
                short       smp_flags = 0;

                if (ogg_page_continued(opg) || si->incompleteCompensation != 0)
                    smp_flags |= mediaSampleNotSync;

                if (duration <= 0) {
                    duration = INCOMPLETE_PAGE_DURATION;
                    si->incompleteCompensation -= INCOMPLETE_PAGE_DURATION;
                } else if (si->incompleteCompensation != 0) {
                    duration += si->incompleteCompensation;
                    si->incompleteCompensation = 0;
                    if (duration <= 0) {
                        ret = badFileFormat;
                        loop = false;
                        break;
                    }
                }

                if (si->insertTime == 0 && si->streamOffsetSamples > 0) {
                    dbg_printf("   -   :++: increasing duration (%ld) by sampleOffset: %ld\n", duration, si->streamOffsetSamples);
                    duration += si->streamOffsetSamples;
                }

                ret = _store_sample_reference(si, &globals->dataOffset, len, duration, smp_flags);
                if (ret != noErr) {
                    loop = false;
                    break;
                }

                if (!globals->usingIdle) {
#if !defined(XIPHQT_FORCE_SINGLE_SAMPLE_REF)
                    if (si->sample_refs_count >= si->sample_refs_size)
                    //if (si->sample_refs_count >= kFSRefsInitial)
#endif
                    {
                        ret = _commit_srefs(globals, si, &movie_changed);
                    }
                }

                if (pos != -1)
                    si->lastGranulePos = pos;
            }
            loop = false;
            break;

        default:
            loop = false;
        }
    } while(loop);

    if (movie_changed)
        NotifyMovieChanged(globals, false);

    return ret;
};
Exemple #10
0
void rip_ogg_process_chunk(RIP_MANAGER_INFO * rmi, LIST * page_list, const char *buf, u_long size, TRACK_INFO * ti)
{
	OGG_PAGE_LIST *ol;
	int header;
	int ret;
	char *buffer;
	//    static ogg_int64_t written = 0;
	//    static unsigned int written = 0;
	//    static int ogg_page2 = 0;

	INIT_LIST_HEAD(page_list);

	debug_printf("-- rip_ogg_process_chunk (%d)\n", size);

	buffer = ogg_sync_buffer(&rmi->ogg_sync, size);
	memcpy(buffer, buf, size);
	ogg_sync_wrote(&rmi->ogg_sync, size);

	do {
		switch (ret = ogg_sync_pageout(&rmi->ogg_sync, &rmi->ogg_pg)) {
		case -1:
			/* -1 if we were not properly synced and had to skip some bytes */
			debug_printf("Hole in ogg, skipping bytes\n");
			break;
		case 0:
			/* 0 if we need more data to verify a page */
			debug_printf("Ogg needs more data\n");
			break;
		case 1:
			/* 1 if we have a page */
			debug_printf("Found an ogg page!\n");

			/* Do stuff needed for decoding vorbis */
			if (ogg_page_bos(&rmi->ogg_pg)) {
				int rc;
				ogg_packet packet;
				ogg_stream_init(&rmi->stream.os, ogg_page_serialno(&rmi->ogg_pg));
				ogg_stream_pagein(&rmi->stream.os, &rmi->ogg_pg);
				rc = ogg_stream_packetout(&rmi->stream.os, &packet);
				if (rc <= 0) {
					printf("Warning: Invalid header page, no packet found\n");
					// null_start (&rmi->stream);
					exit(1);
				} else if (packet.bytes >= 7 && memcmp(packet.packet, "\001vorbis", 7) == 0) {
					vorbis_start(&rmi->stream);
				}
			}
			header = vorbis_process(rmi, &rmi->stream, &rmi->ogg_pg, ti);
			if (ogg_page_eos(&rmi->ogg_pg)) {
				vorbis_end(&rmi->stream);
			}

			/* Create ogg page boundary struct */
			ol = (OGG_PAGE_LIST *) malloc(sizeof(OGG_PAGE_LIST));
			if (!ol) {
				printf("Malloc error\n");
				exit(1);
			}
			ol->m_page_len = rmi->ogg_pg.header_len + rmi->ogg_pg.body_len;
			ol->m_page_flags = 0;

			/* *****************************************************
			   Create header buffer for relay stream. A pointer to the 
			   header buffer will attached to all pages after page 2.
			   If a relay connects in the middle of a song, we send 
			   the header to the relay. Finally, the memory for the 
			   header is freed when the last page of the song is 
			   ejected from the cbuf. 
			   ** ***************************************************** */
			if (ogg_page_bos(&rmi->ogg_pg)) {
				/* First page in song */
				ol->m_page_flags |= OGG_PAGE_BOS;
				ol->m_header_buf_ptr = 0;
				ol->m_header_buf_len = 0;
				rmi->ogg_curr_header = (char *)malloc(ol->m_page_len);
				rmi->ogg_curr_header_len = ol->m_page_len;
				memcpy(rmi->ogg_curr_header, rmi->ogg_pg.header, rmi->ogg_pg.header_len);
				memcpy(rmi->ogg_curr_header + rmi->ogg_pg.header_len,
				       rmi->ogg_pg.body, rmi->ogg_pg.body_len);
			} else if (header) {
				/* Second or third page in song */
				ol->m_page_flags |= OGG_PAGE_2;
				ol->m_header_buf_ptr = 0;
				ol->m_header_buf_len = 0;
				rmi->ogg_curr_header = (char *)
				    realloc(rmi->ogg_curr_header, rmi->ogg_curr_header_len + ol->m_page_len);
				memcpy(rmi->ogg_curr_header + rmi->ogg_curr_header_len,
				       rmi->ogg_pg.header, rmi->ogg_pg.header_len);
				memcpy(rmi->ogg_curr_header + rmi->ogg_curr_header_len
				       + rmi->ogg_pg.header_len, rmi->ogg_pg.body, rmi->ogg_pg.body_len);
				rmi->ogg_curr_header_len += ol->m_page_len;
			} else if (!ogg_page_eos(&rmi->ogg_pg)) {
				/* Middle pages in song */
				ol->m_header_buf_ptr = rmi->ogg_curr_header;
				ol->m_header_buf_len = rmi->ogg_curr_header_len;
			} else {
				/* Last page in song */
				ol->m_page_flags |= OGG_PAGE_EOS;
				ol->m_header_buf_ptr = rmi->ogg_curr_header;
				ol->m_header_buf_len = rmi->ogg_curr_header_len;
				rmi->ogg_curr_header = 0;
				rmi->ogg_curr_header_len = 0;
			}

			debug_printf("OGG_PAGE\n"
				     "  header_len = %d\n"
				     "  body_len = %d\n"
				     "  serial no = %d\n"
				     "  page no = %d\n"
				     "  bos? = %d\n"
				     "  eos? = %d\n",
				     rmi->ogg_pg.header_len,
				     rmi->ogg_pg.body_len,
				     ogg_page_serialno(&rmi->ogg_pg),
				     ogg_page_pageno(&rmi->ogg_pg),
				     ogg_page_bos(&rmi->ogg_pg), ogg_page_eos(&rmi->ogg_pg));
			list_add_tail(&(ol->m_list), page_list);
			break;
		}
	} while (ret != 0);

	debug_printf("OGG_SYNC state:\n"
		     "  storage = %d\n"
		     "  fill = %d\n"
		     "  returned = %d\n"
		     "  unsynced = %d\n"
		     "  headerbytes = %d\n"
		     "  bodybytes = %d\n",
		     rmi->ogg_sync.storage,
		     rmi->ogg_sync.fill,
		     rmi->ogg_sync.returned,
		     rmi->ogg_sync.unsynced, rmi->ogg_sync.headerbytes, rmi->ogg_sync.bodybytes);
	//    return 1;
}