Ejemplo n.º 1
0
// ReadHeaders allows to init info and comment from a private codec data payload
// when no Ogg stream is available. Info and comment must be initialised beforehand.
func ReadHeaders(codecPriv []byte, info *vorbis.Info, comment *vorbis.Comment) error {
	if len(codecPriv) == 0 {
		return errors.New("vorbis decoder: no codec private data")
	}
	headerSizes := make([]int, 3)
	headers := make([][]byte, 3)
	p := codecPriv

	if p[0] == 0x00 && p[1] == 0x30 {
		for i := 0; i < 3; i++ {
			headerSizes[i] = int(uint16(p[0])<<8 | uint16(p[1]))
			headers[i] = p
			p = p[headerSizes[i]:]
		}
	} else if p[0] == 0x02 {
		offset := 1
		p = p[1:]
		for i := 0; i < 2; i++ {
			headerSizes[i] = 0
			for (p[0] == 0xFF) && offset < len(codecPriv) {
				headerSizes[i] += 0xFF
				offset++
				p = p[1:]
			}
			if offset >= len(codecPriv)-1 {
				return errors.New("vorbis decoder: header sizes damaged")
			}
			headerSizes[i] += int(p[0])
			offset++
			p = p[1:]
		}
		headerSizes[2] = len(codecPriv) - headerSizes[0] - headerSizes[1] - offset
		headers[0] = codecPriv[offset:]
		headers[1] = codecPriv[offset+headerSizes[0]:]
		headers[2] = codecPriv[offset+headerSizes[0]+headerSizes[1]:]
	} else {
		return fmt.Errorf("vorbis decoder: initial header len is wrong: %d", p[0])
	}
	for i := 0; i < 3; i++ {
		packet := vorbis.OggPacket{
			BOS:    b(i == 0),
			Bytes:  headerSizes[i],
			Packet: headers[i],
		}
		if ret := vorbis.SynthesisHeaderin(info, comment, &packet); ret < 0 {
			return fmt.Errorf("vorbis decoder: %d. header damaged", i+1)
		}
	}
	return nil
}
Ejemplo n.º 2
0
func (d *Decoder) readStreamHeaders(r io.Reader) error {
	d.readChunk(r)

	// Read the first page
	if ret := vorbis.OggSyncPageout(&d.syncState, &d.page); ret != 1 {
		return errors.New("vorbis: not a valid Ogg bitstream")
	}

	// Init the logical bitstream with serial number stored in the page
	vorbis.OggStreamInit(&d.streamState, vorbis.OggPageSerialno(&d.page))

	vorbis.InfoInit(&d.info)
	vorbis.CommentInit(&d.comment)

	// Add a complete page to the bitstream
	if ret := vorbis.OggStreamPagein(&d.streamState, &d.page); ret < 0 {
		return errors.New("vorbis: the supplied page does not belong this Vorbis stream")
	}
	// Get the first packet
	if ret := vorbis.OggStreamPacketout(&d.streamState, &d.packet); ret != 1 {
		return errors.New("vorbis: unable to fetch initial Vorbis packet from the first page")
	}
	// Finally decode the header packet
	if ret := vorbis.SynthesisHeaderin(&d.info, &d.comment, &d.packet); ret < 0 {
		return fmt.Errorf("vorbis: unable to decode the initial Vorbis header: %d", ret)
	}

	var headersRead int
forPage:
	for headersRead < 2 {
		if res := vorbis.OggSyncPageout(&d.syncState, &d.page); res < 0 {
			// bytes have been skipped, try to sync again
			continue forPage
		} else if res == 0 {
			// go get more data
			if _, err := d.readChunk(r); err != nil {
				return errors.New("vorbis: got EOF while reading Vorbis headers")
			}
			continue forPage
		}
		// page is synced at this point
		vorbis.OggStreamPagein(&d.streamState, &d.page)
		for headersRead < 2 {
			if ret := vorbis.OggStreamPacketout(&d.streamState, &d.packet); ret < 0 {
				return errors.New("vorbis: data is missing near the secondary Vorbis header")
			} else if ret == 0 {
				// no packets left on the page, go get a new one
				continue forPage
			}
			if ret := vorbis.SynthesisHeaderin(&d.info, &d.comment, &d.packet); ret < 0 {
				return errors.New("vorbis: unable to read the secondary Vorbis header")
			}
			headersRead++
		}
	}

	d.info.Deref()
	d.comment.Deref()
	d.comment.UserComments = make([][]byte, d.comment.Comments)
	d.comment.Deref()
	return nil
}