rendered paste body# PySoy's textures.Video class
#
# Copyright (C) 2006,2007,2008 PySoy Group
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program; if not, see http://www.gnu.org/licenses
#
# $Id: Video.pym 1265 2008-05-18 17:14:51Z ArcRiley $
cdef class Video (Texture) :
'''PySoy textures.Video Class
Renders an Ogg Theora stream to a texture
'''
############################################################################
#
# C functions
#
cdef int _load(self, void* _data, int _size) nogil :
cdef int _x, _y, _tx, _ty, _yl, _yc
cdef int _py, _pu, _pv, _pr, _pg, _pb
cdef ogg.ogg_page* _page
cdef ogg.yuv_buffer _yuv
cdef ogg.ogg_packet _packet
cdef double _start # for benchmarking
cdef gl.GLubyte* _rgbx
if _data == NULL :
stdio.printf('done decoding.\n')
if self._stage > 0 :
ogg.ogg_stream_clear(&self._stream)
ogg.theora_info_clear(&self._info)
ogg.theora_comment_clear(&self._comment)
ogg.theora_clear(&self._decode)
return 0
_page = <ogg.ogg_page*> _data
#
# For Chaining/Looping
if ogg.ogg_page_bos(_page) :
if self._stage > 0 :
ogg.ogg_stream_clear(&self._stream)
ogg.theora_info_clear(&self._info)
ogg.theora_comment_clear(&self._comment)
ogg.theora_clear(&self._decode)
self._startTime = self._startTime + self._frameTime
self._frameTime = 0
else :
self._startTime = _time()
self._stage = 0
#
# Read Page 0
if self._stage == 0 :
ogg.ogg_stream_init(&self._stream, ogg.ogg_page_serialno(_page))
ogg.theora_info_init(&self._info)
ogg.theora_comment_init(&self._comment)
self._stage = 1
# Read in the page if not -1
if self._stage > 0 :
ogg.ogg_stream_pagein(&self._stream, _page)
# Read pre-data pages (if any)
if self._stage == 1 :
if ogg.ogg_page_granulepos(_page) == 0 :
while ogg.ogg_stream_packetout(&self._stream, &_packet) :
if ogg.theora_decode_header(&self._info, &self._comment,&_packet)<0 :
# Error in header, clear what we've setup and bail
ogg.ogg_stream_clear(&self._stream)
ogg.theora_info_clear(&self._info)
ogg.theora_comment_clear(&self._comment)
self._stage = -1
return 0
if ogg.ogg_page_pageno(_page) == 0 :
self._resize(1, 3, self._squareup(self._info.frame_width),
self._squareup(self._info.frame_height), 1)
self._scaleX = <float> self._info.frame_width / <float> self._width
self._scaleY = <float> self._info.frame_height / <float> self._height
self._aspect = ( <float> self._info.frame_width / \
<float> self._info.frame_height ) * \
( <float> self._info.aspect_numerator / \
<float> self._info.aspect_denominator )
else :
ogg.theora_decode_init(&self._decode, &self._info)
self._stage = 2
if self._stage == 2 :
# Theora frames are 1:1 with Ogg packets, but packets != pages
while ogg.ogg_stream_packetout(&self._stream, &_packet) :
ogg.theora_decode_packetin(&self._decode, &_packet)
self._frameTime = ogg.theora_granule_time(&self._decode,
ogg.ogg_page_granulepos(_page))
ogg.theora_decode_YUVout(&self._decode, &_yuv)
#
# tx/ty = texels x/y offset
# yl/yc = yuv l/c offsets
#
# This can and should be optimized further
#_start = _time()
_rgbx = <gl.GLubyte*> py.PyMem_Malloc(self._width * 4)
for _y from 0 <= _y < self._info.frame_height :
_ty = (self._info.frame_height - _y) * self._width
_yl = _y * _yuv.y_stride
_yc = (_y/2) * _yuv.uv_stride
oil.oil_yuv2rgbx_sub2_u8(
_rgbx,
_yuv.y + _yl,
_yuv.u + _yc,
_yuv.v + _yc,
self._info.frame_width)
#
# copy rgbx to rgb, this needs to be optimized
for _x from 0 <= _x < self._width :
_tx = (_ty + _x) * 3
self._texels[_tx ] = _rgbx[(_x*4) ]
self._texels[_tx + 1] = _rgbx[(_x*4) + 1]
self._texels[_tx + 2] = _rgbx[(_x*4) + 2]
# _py = _yuv.y[_yl + x]
# _pu = _yuv.u[_yc + (x/2)]
# _pv = _yuv.v[_yc + (x/2)]
# _pr = _py + _tableRV[_pv]
# _pg = _py - _tableGV[_pv] - _tableGU[_pu]
# _pb = _py + _tableBU[_pu]
# if _pr < 0 :
# _pr = 0
# if _pg < 0 :
# _pg = 0
# if _pb < 0 :
# _pb = 0
# if _pr > 255 :
# _pr = 255
# if _pg > 255 :
# _pg = 255
# if _pb > 255 :
# _pb = 255
# self._texels[_tx ] = _pr
# self._texels[_tx+1] = _pg
# self._texels[_tx+2] = _pb
py.PyMem_Free(_rgbx)
self._update = 1
return 1
cdef int _save(self, void *_data, int _size) nogil :
cdef ogg.ogg_page *_page
_page = <ogg.ogg_page*> _data
return 1
cdef int _ready(self) nogil :
cdef double _now
_now = _time()
if self._startTime + self._frameTime < _now :
return 1
return 0
############################################################################
#
# Properties
#
property offset :
def __get__(self) :
return self._frameTime