source: src/textures/Video.pym @ 1345:ff8ef9c6bbb7

Revision 1345:ff8ef9c6bbb7, 5.6 KB checked in by Arc Riley <arcriley@…>, 6 years ago (diff)

Happy New Year! (copyright string update)

Line 
1# PySoy's textures.Video class
2#
3# Copyright (C) 2006,2007,2008,2009 PySoy Group
4#
5#  This program is free software; you can redistribute it and/or modify
6#  it under the terms of the GNU Affero General Public License as published
7#  by the Free Software Foundation, either version 3 of the License, or
8#  (at your option) any later version.
9#
10#  This program is distributed in the hope that it will be useful,
11#  but WITHOUT ANY WARRANTY; without even the implied warranty of
12#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13#  GNU Affero General Public License for more details.
14#
15#  You should have received a copy of the GNU Affero General Public License
16#  along with this program; if not, see http://www.gnu.org/licenses
17#
18# $Id: Video.pym 1393 2008-12-31 23:51:25Z ArcRiley $
19
20
21cdef class Video (Texture) :
22  '''PySoy textures.Video Class
23
24    Renders an Ogg Theora stream to a texture
25  '''
26
27  ############################################################################
28  #
29  # C functions
30  #
31 
32  cdef int _load(self, void* _data, int _size) nogil :
33    cdef int x, y, _cx, _cy, _tx, _ty, _yl, _yc
34    cdef int _py, _pu, _pv, _pr, _pg, _pb
35    cdef ogg.ogg_page*   _page
36    cdef ogg.yuv_buffer  _yuv
37    cdef ogg.ogg_packet  _packet
38    cdef double          _start  # for benchmarking
39    if _data == NULL :
40      stdio.printf('done decoding.\n')
41      if self._stage > 0 :
42        ogg.ogg_stream_clear(&self._stream)
43        ogg.theora_info_clear(&self._info)
44        ogg.theora_comment_clear(&self._comment)
45        ogg.theora_clear(&self._decode)
46      return 0
47    _page = <ogg.ogg_page*> _data
48    #
49    # For Chaining/Looping
50    if ogg.ogg_page_bos(_page) :
51      if self._stage > 0 :
52        ogg.ogg_stream_clear(&self._stream)
53        ogg.theora_info_clear(&self._info)
54        ogg.theora_comment_clear(&self._comment)
55        ogg.theora_clear(&self._decode)
56        self._startTime = self._startTime + self._frameTime
57        self._frameTime = 0
58      else :
59        self._startTime = _time()
60      self._stage = 0
61    #
62    # Read Page 0
63    if self._stage == 0 :
64      ogg.ogg_stream_init(&self._stream, ogg.ogg_page_serialno(_page))
65      ogg.theora_info_init(&self._info)
66      ogg.theora_comment_init(&self._comment)
67      self._stage = 1
68    # Read in the page if not -1
69    if self._stage > 0 :
70      ogg.ogg_stream_pagein(&self._stream, _page)
71    # Read pre-data pages (if any)
72    if self._stage == 1 :
73      if ogg.ogg_page_granulepos(_page) == 0 :
74        while ogg.ogg_stream_packetout(&self._stream, &_packet) :
75          if ogg.theora_decode_header(&self._info, &self._comment,&_packet)<0 :
76            # Error in header, clear what we've setup and bail
77            ogg.ogg_stream_clear(&self._stream)
78            ogg.theora_info_clear(&self._info)
79            ogg.theora_comment_clear(&self._comment)
80            self._stage = -1
81            return 0
82        if ogg.ogg_page_pageno(_page) == 0 :
83          self._resize(1, 3, self._squareup(self._info.frame_width),
84                          self._squareup(self._info.frame_height), 1)
85          self._scaleX = <float> self._info.frame_width  / <float> self._width
86          self._scaleY = <float> self._info.frame_height / <float> self._height
87          self._aspect = ( <float> self._info.frame_width / \
88                           <float> self._info.frame_height ) * \
89                         ( <float> self._info.aspect_numerator / \
90                           <float> self._info.aspect_denominator )
91      else :
92        ogg.theora_decode_init(&self._decode, &self._info)
93        self._stage = 2
94    if self._stage == 2 :
95      # Theora frames are 1:1 with Ogg packets, but packets != pages
96      while ogg.ogg_stream_packetout(&self._stream, &_packet) :
97        ogg.theora_decode_packetin(&self._decode, &_packet)
98        self._frameTime = ogg.theora_granule_time(&self._decode,
99                                              ogg.ogg_page_granulepos(_page))
100        ogg.theora_decode_YUVout(&self._decode, &_yuv)
101        #
102        # cx/cy = chroma x/y due to 4:2:0
103        # tx/ty = texels x/y offset
104        # yl/yc = yuv l/c offsets
105        #
106        # This can and should be optimized further
107        #_start = _time()
108        _cx = self._info.frame_width
109        _cy = self._info.frame_height
110        for y from 0 <= y < _cy :
111          _ty = (self._info.frame_height - y) * self._width
112          _yl = y * _yuv.y_stride
113          _yc = (y/2) * _yuv.uv_stride
114          for x from 0 <= x < _cx :
115            _tx = (_ty + x) * 3
116            _py = _yuv.y[_yl + x]
117            _pu = _yuv.u[_yc + (x/2)]
118            _pv = _yuv.v[_yc + (x/2)]
119            _pr = _py + _tableRV[_pv]
120            _pg = _py - _tableGV[_pv] - _tableGU[_pu]
121            _pb = _py + _tableBU[_pu]
122            if _pr < 0 :
123              _pr = 0
124            if _pg < 0 :
125              _pg = 0
126            if _pb < 0 :
127              _pb = 0
128            if _pr > 255 :
129              _pr = 255
130            if _pg > 255 :
131              _pg = 255
132            if _pb > 255 :
133              _pb = 255
134            self._texels[_tx  ] = _pr
135            self._texels[_tx+1] = _pg
136            self._texels[_tx+2] = _pb
137        self._update = 1
138    return 1
139
140
141  cdef int _save(self, void *_data, int _size) nogil :
142    cdef ogg.ogg_page   *_page
143    _page = <ogg.ogg_page*> _data
144    return 1
145
146
147  cdef int _ready(self) nogil :
148    cdef double  _now
149    _now = _time()
150    if self._startTime + self._frameTime < _now :
151      return 1
152    return 0
153
154
155  ############################################################################
156  #
157  # Properties
158  #
159 
160  property offset :
161    def __get__(self) :
162      return self._frameTime
Note: See TracBrowser for help on using the repository browser.