Пример #1
0
    def _update_play_cursor(self):
        if not self._al_source:
            return

        self._lock.acquire()
        context.lock()

        # Release spent buffers
        processed = al.ALint()
        al.alGetSourcei(self._al_source, al.AL_BUFFERS_PROCESSED, processed)
        processed = processed.value
        if processed:
            buffers = (al.ALuint * processed)()
            al.alSourceUnqueueBuffers(self._al_source, len(buffers), buffers)
            error = al.alGetError()
            if error != 0:
                if _debug_buffers:
                    print ("Source unqueue error: " + str(error))
            else:
                for b in buffers:
                    bufferPool.dequeueBuffer(self._al_source, b)
        context.unlock()

        if processed:
            if len(self._buffer_timestamps) == processed and self._buffer_timestamps[-1] is not None:
                # Underrun, take note of timestamp.
                # We check that the timestamp is not None, because otherwise
                # our source could have been cleared.
                self._underrun_timestamp = self._buffer_timestamps[-1] + self._buffer_sizes[-1] / float(
                    self.source_group.audio_format.bytes_per_second
                )
            self._buffer_cursor += sum(self._buffer_sizes[:processed])
            del self._buffer_sizes[:processed]
            del self._buffer_timestamps[:processed]

            if not context.have_1_1:
                self._buffer_system_time = time.time()

        # Update play cursor using buffer cursor + estimate into current
        # buffer
        if context.have_1_1:
            bytes = al.ALint()
            context.lock()
            al.alGetSourcei(self._al_source, al.AL_BYTE_OFFSET, bytes)
            context.unlock()
            if _debug:
                print "got bytes offset", bytes.value
            self._play_cursor = self._buffer_cursor + bytes.value
        else:
            # Interpolate system time past buffer timestamp
            self._play_cursor = self._buffer_cursor + int(
                (time.time() - self._buffer_system_time) * self.source_group.audio_format.bytes_per_second
            )

        # Process events
        while self._events and self._events[0][0] < self._play_cursor:
            _, event = self._events.pop(0)
            event._sync_dispatch_to_player(self.player)

        self._lock.release()
Пример #2
0
 def _al_play(self):
     context.lock()
     state = al.ALint()
     al.alGetSourcei(self._al_source, al.AL_SOURCE_STATE, state)
     if state.value != al.AL_PLAYING:
         al.alSourcePlay(self._al_source)
     context.unlock()
Пример #3
0
 def _al_play(self):
     context.lock()
     state = al.ALint()
     al.alGetSourcei(self._al_source, al.AL_SOURCE_STATE, state)
     if state.value != al.AL_PLAYING:
         al.alSourcePlay(self._al_source)
     context.unlock()
Пример #4
0
 def _al_play(self):
     if _debug:
         print 'OpenALAudioPlayer._al_play()'
     with context.lock:
         state = al.ALint()
         al.alGetSourcei(self._al_source, al.AL_SOURCE_STATE, state)
         if state.value != al.AL_PLAYING:
             al.alSourcePlay(self._al_source)
Пример #5
0
 def _al_play(self):
     if _debug:
         print 'OpenALAudioPlayer._al_play()'
     with context.lock:
         state = al.ALint()
         al.alGetSourcei(self._al_source, al.AL_SOURCE_STATE, state)
         if state.value != al.AL_PLAYING:
             al.alSourcePlay(self._al_source)
Пример #6
0
    def refill(self, write_size):
        if _debug:
            print 'refill', write_size

        self._lock.acquire()

        while write_size > self._min_buffer_size:
            audio_data = self.source_group.get_audio_data(write_size)
            if not audio_data:
                self._eos = True
                self._events.append(
                    (self._write_cursor, MediaEvent(0, 'on_eos')))
                self._events.append(
                    (self._write_cursor, MediaEvent(0, 'on_source_group_eos')))
                break

            for event in audio_data.events:
                cursor = self._write_cursor + event.timestamp * \
                    self.source_group.audio_format.bytes_per_second
                self._events.append((cursor, event))

            context.lock()
            buffer = bufferPool.getBuffer(self._al_source)
            al.alBufferData(buffer, 
                            self._al_format,
                            audio_data.data,
                            audio_data.length,
                            self.source_group.audio_format.sample_rate)
            if _debug_buffers:
                error = al.alGetError()
                if error != 0:
                    print("BUFFER DATA ERROR: " + str(error))
            al.alSourceQueueBuffers(self._al_source, 1, ctypes.byref(buffer))
            if _debug_buffers:
                error = al.alGetError()
                if error != 0:
                    print("QUEUE BUFFER ERROR: " + str(error)) 
            context.unlock()

            self._write_cursor += audio_data.length
            self._buffer_sizes.append(audio_data.length)
            self._buffer_timestamps.append(audio_data.timestamp)
            write_size -= audio_data.length

        # Check for underrun stopping playback
        if self._playing:
            state = al.ALint()
            context.lock()
            al.alGetSourcei(self._al_source, al.AL_SOURCE_STATE, state)
            if state.value != al.AL_PLAYING:
                if _debug:
                    print 'underrun'
                al.alSourcePlay(self._al_source)
            context.unlock()

        self._lock.release()
Пример #7
0
    def refill(self, write_size):
        if _debug:
            print 'refill', write_size

        self._lock.acquire()

        while write_size > self._min_buffer_size:
            audio_data = self.source_group.get_audio_data(write_size)
            if not audio_data:
                self._eos = True
                self._events.append(
                    (self._write_cursor, MediaEvent(0, 'on_eos')))
                self._events.append(
                    (self._write_cursor, MediaEvent(0, 'on_source_group_eos')))
                break

            for event in audio_data.events:
                cursor = self._write_cursor + event.timestamp * \
                    self.source_group.audio_format.bytes_per_second
                self._events.append((cursor, event))

            context.lock()
            buffer = bufferPool.getBuffer(self._al_source)
            al.alBufferData(buffer,
                            self._al_format,
                            audio_data.data,
                            audio_data.length,
                            self.source_group.audio_format.sample_rate)
            if _debug_buffers:
                error = al.alGetError()
                if error != 0:
                    print("BUFFER DATA ERROR: " + str(error))
            al.alSourceQueueBuffers(self._al_source, 1, ctypes.byref(buffer))
            if _debug_buffers:
                error = al.alGetError()
                if error != 0:
                    print("QUEUE BUFFER ERROR: " + str(error))
            context.unlock()

            self._write_cursor += audio_data.length
            self._buffer_sizes.append(audio_data.length)
            self._buffer_timestamps.append(audio_data.timestamp)
            write_size -= audio_data.length

        # Check for underrun stopping playback
        if self._playing:
            state = al.ALint()
            context.lock()
            al.alGetSourcei(self._al_source, al.AL_SOURCE_STATE, state)
            if state.value != al.AL_PLAYING:
                if _debug:
                    print 'underrun'
                al.alSourcePlay(self._al_source)
            context.unlock()

        self._lock.release()
Пример #8
0
    def _update_play_cursor(self):
        if not self._al_source:
            return

        self._lock.acquire()
        context.lock()

        # Release spent buffers
        processed = al.ALint()
        al.alGetSourcei(self._al_source, al.AL_BUFFERS_PROCESSED, processed)
        processed = processed.value
        if processed:
            buffers = (al.ALuint * processed)()
            al.alSourceUnqueueBuffers(self._al_source, len(buffers), buffers)
            al.alDeleteBuffers(len(buffers), buffers)
        context.unlock()

        if processed:
            if len(self._buffer_timestamps) == processed:
                # Underrun, take note of timestamp
                self._underrun_timestamp = \
                    self._buffer_timestamps[-1] + \
                    self._buffer_sizes[-1] / \
                        float(self.source_group.audio_format.bytes_per_second)
            self._buffer_cursor += sum(self._buffer_sizes[:processed])
            del self._buffer_sizes[:processed]
            del self._buffer_timestamps[:processed]

            if not context.have_1_1:
                self._buffer_system_time = time.time()

        # Update play cursor using buffer cursor + estimate into current
        # buffer
        if context.have_1_1:
            bytes = al.ALint()
            context.lock()
            al.alGetSourcei(self._al_source, al.AL_BYTE_OFFSET, bytes)
            context.unlock()
            if _debug:
                print 'got bytes offset', bytes.value
            self._play_cursor = self._buffer_cursor + bytes.value
        else:
            # Interpolate system time past buffer timestamp
            self._play_cursor = \
                self._buffer_cursor + int(
                    (time.time() - self._buffer_system_time) * \
                        self.source_group.audio_format.bytes_per_second)

        # Process events
        while self._events and self._events[0][0] < self._play_cursor:
            _, event = self._events.pop(0)
            event._sync_dispatch_to_player(self.player)

        self._lock.release()
Пример #9
0
    def _update_play_cursor(self):
        if not self._al_source:
            return

        self._lock.acquire()
        context.lock()

        # Release spent buffers
        processed = al.ALint()
        al.alGetSourcei(self._al_source, al.AL_BUFFERS_PROCESSED, processed)
        processed = processed.value
        if processed:
            buffers = (al.ALuint * processed)()
            al.alSourceUnqueueBuffers(self._al_source, len(buffers), buffers)
            al.alDeleteBuffers(len(buffers), buffers)
        context.unlock()

        if processed:
            if len(self._buffer_timestamps) == processed:
                # Underrun, take note of timestamp
                self._underrun_timestamp = \
                    self._buffer_timestamps[-1] + \
                    self._buffer_sizes[-1] / \
                        float(self.source_group.audio_format.bytes_per_second)
            self._buffer_cursor += sum(self._buffer_sizes[:processed])
            del self._buffer_sizes[:processed]
            del self._buffer_timestamps[:processed]

            if not context.have_1_1:
                self._buffer_system_time = time.time()

        # Update play cursor using buffer cursor + estimate into current
        # buffer
        if context.have_1_1:
            bytes = al.ALint()
            context.lock()
            al.alGetSourcei(self._al_source, al.AL_BYTE_OFFSET, bytes)
            context.unlock()
            if _debug:
                print 'got bytes offset', bytes.value
            self._play_cursor = self._buffer_cursor + bytes.value
        else:
            # Interpolate system time past buffer timestamp
            self._play_cursor = \
                self._buffer_cursor + int(
                    (time.time() - self._buffer_system_time) * \
                        self.source_group.audio_format.bytes_per_second)

        # Process events
        while self._events and self._events[0][0] < self._play_cursor:
            _, event = self._events.pop(0)
            event._sync_dispatch_to_player(self.player)

        self._lock.release()
Пример #10
0
    def refill(self, write_size):
        if _debug:
            print "refill", write_size

        self._lock.acquire()

        while write_size > self._min_buffer_size:
            audio_data = self.source_group.get_audio_data(write_size)
            if not audio_data:
                self._eos = True
                self._events.append((self._write_cursor, MediaEvent(0, "on_eos")))
                self._events.append((self._write_cursor, MediaEvent(0, "on_source_group_eos")))
                break

            for event in audio_data.events:
                cursor = self._write_cursor + event.timestamp * self.source_group.audio_format.bytes_per_second
                self._events.append((cursor, event))

            buffer = al.ALuint()
            context.lock()
            al.alGenBuffers(1, buffer)
            al.alBufferData(
                buffer, self._al_format, audio_data.data, audio_data.length, self.source_group.audio_format.sample_rate
            )
            al.alSourceQueueBuffers(self._al_source, 1, ctypes.byref(buffer))
            context.unlock()

            self._write_cursor += audio_data.length
            self._buffer_sizes.append(audio_data.length)
            self._buffer_timestamps.append(audio_data.timestamp)
            write_size -= audio_data.length

        # Check for underrun stopping playback
        if self._playing:
            state = al.ALint()
            context.lock()
            al.alGetSourcei(self._al_source, al.AL_SOURCE_STATE, state)
            if state.value != al.AL_PLAYING:
                if _debug:
                    print "underrun"
                al.alSourcePlay(self._al_source)
            context.unlock()

        self._lock.release()
Пример #11
0
    alcontext = alc.alcCreateContext(device, None)
    alc.alcMakeContextCurrent(alcontext)

    source = al.ALuint()
    al.alGenSources(1, source)

    pool = BufferPool()

    # avcodec
    init()
    container = open(sys.argv[1])
    stream = get_audio_stream(container)

    decoder = AVCodecDecoder(container, stream)

    while True:
        buffer = pool.get_buffer()
        if not decoder.fill_buffer(buffer):
            break
        al.alSourceQueueBuffers(source, 1, buffer)

    al.alSourcePlay(source)

    while True:
        value = al.ALint()
        al.alGetSourcei(source, al.AL_SOURCE_STATE, value)
        if value.value == al.AL_STOPPED:
            break

        time.sleep(1)
Пример #12
0
class AVCodecDecoder:
    def __init__(self, container, stream):
        self.codec = get_codec(container, stream)
        if self.codec.contents.channels == 1:
            self.buffer_format = al.AL_FORMAT_MONO16
        elif self.codec.contents.channels == 2:
            self.buffer_format = al.AL_FORMAT_STEREO16
        else:
            raise Exception('Invalid number of channels')
        self.sample_rate = self.codec.contents.sample_rate

        self.container = container
        self.stream = stream
        self.packet = avformat.AVPacket()
        self.sample_buffer = \
            (ctypes.c_int16 * (avcodec.AVCODEC_MAX_AUDIO_FRAME_SIZE / 2))()

        self.read_packet()

    def read_packet(self):
        while True:
            if self.packet.data:
                self.packet.data = None
                self.packet.size = 0

            if avformat.av_read_packet(self.container, self.packet) < 0:
                break

            if self.packet.stream_index == self.stream:
                break

        self.packet_data = self.packet.data
        self.packet_size = self.packet.size

    def fill_buffer(self, buffer):
        if self.packet_size <= 0:
            self.read_packet()

        if self.packet_size == 0:  # EOS
            return False

        sample_buffer_size = ctypes.c_int()
        len = avcodec.avcodec_decode_audio(self.codec, self.sample_buffer,
                                           sample_buffer_size,
                                           self.packet_data, self.packet_size)
        if len < 0:
            # Error, skip frame
            raise Exception('frame error TODO')

        if sample_buffer_size.value > 0:
            al.alBufferData(buffer, self.buffer_format, self.sample_buffer,
                            sample_buffer_size.value, self.sample_rate)

        # Advance buffer pointer
        self.packet_data = ctypes.c_uint8.from_address(
            ctypes.addressof(self.packet_data) + len)
        self.packet_size -= len

        return True

    import sys

    # openal
    device = alc.alcOpenDevice(None)
    if not device:
        raise Exception('No OpenAL device.')

    alcontext = alc.alcCreateContext(device, None)
    alc.alcMakeContextCurrent(alcontext)

    source = al.ALuint()
    al.alGenSources(1, source)

    pool = BufferPool()

    # avcodec
    init()
    container = open(sys.argv[1])
    stream = get_audio_stream(container)

    decoder = AVCodecDecoder(container, stream)

    while True:
        buffer = pool.get_buffer()
        if not decoder.fill_buffer(buffer):
            break
        al.alSourceQueueBuffers(source, 1, buffer)

    al.alSourcePlay(source)

    while True:
        value = al.ALint()
        al.alGetSourcei(source, al.AL_SOURCE_STATE, value)
        if value.value == al.AL_STOPPED:
            break

        time.sleep(1)
Пример #13
0
    def _update_play_cursor(self):
        if not self._al_source:
            return

        with self._lock:
            with context.lock:

                # Release spent buffers
                processed = al.ALint()
                al.alGetSourcei(self._al_source, al.AL_BUFFERS_PROCESSED,
                                processed)
                processed = processed.value
                if _debug_buffers:
                    print("Processed buffer count:", processed)
                if processed:
                    buffers = (al.ALuint * processed)()
                    al.alSourceUnqueueBuffers(self._al_source, len(buffers),
                                              buffers)
                    error = al.alGetError()
                    if error != 0:
                        if _debug_buffers:
                            print("Source unqueue error: " + str(error))
                    else:
                        for b in buffers:
                            bufferPool.dequeueBuffer(self._al_source, b)

            if processed:
                if (len(self._buffer_timestamps) == processed
                        and self._buffer_timestamps[-1] is not None):
                    # Underrun, take note of timestamp.
                    # We check that the timestamp is not None, because otherwise
                    # our source could have been cleared.
                    self._underrun_timestamp = \
                        self._buffer_timestamps[-1] + \
                        self._buffer_sizes[-1] / \
                            float(self.source_group.audio_format.bytes_per_second)
                self._buffer_cursor += sum(self._buffer_sizes[:processed])
                del self._buffer_sizes[:processed]
                del self._buffer_timestamps[:processed]

                if not context.have_1_1:
                    self._buffer_system_time = time.time()

            # Update play cursor using buffer cursor + estimate into current
            # buffer
            if context.have_1_1:
                byte_offset = al.ALint()
                with context.lock:
                    al.alGetSourcei(self._al_source, al.AL_BYTE_OFFSET,
                                    byte_offset)
                if _debug:
                    print 'Current offset in bytes:', byte_offset.value
                self._play_cursor = self._buffer_cursor + byte_offset.value
            else:
                # Interpolate system time past buffer timestamp
                self._play_cursor = \
                    self._buffer_cursor + int(
                        (time.time() - self._buffer_system_time) * \
                            self.source_group.audio_format.bytes_per_second)

            # Process events
            while self._events and self._events[0][0] < self._play_cursor:
                _, event = self._events.pop(0)
                event._sync_dispatch_to_player(self.player)
Пример #14
0
    alcontext = alc.alcCreateContext(device, None)
    alc.alcMakeContextCurrent(alcontext)

    source = al.ALuint()
    al.alGenSources(1, source)

    pool = BufferPool()

    # avcodec
    init()
    container = open(sys.argv[1])
    stream = get_audio_stream(container)
    
    decoder = AVCodecDecoder(container, stream)
    
    while True:
        buffer = pool.get_buffer()
        if not decoder.fill_buffer(buffer):
            break
        al.alSourceQueueBuffers(source, 1, buffer)

    al.alSourcePlay(source)

    while True:
        value = al.ALint()
        al.alGetSourcei(source, al.AL_SOURCE_STATE, value)
        if value.value == al.AL_STOPPED:
            break

        time.sleep(1)