source: src/textures/Video.pym @ 1359:e7f02df1beb1

Revision 1359:e7f02df1beb1, 4.9 KB checked in by Arc Riley <arcriley@…>, 6 years ago (diff)

Ticket #968 :

  • finished, closing ticket
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 1462 2009-01-11 05:26:23Z 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             _y
34    cdef ogg.ogg_page*   _page
35    cdef ogg.yuv_buffer  _yuv
36    cdef ogg.ogg_packet  _packet
37    cdef double          _start  # for benchmarking
38    if _data == NULL :
39      stdio.printf('done decoding.\n')
40      if self._stage > 0 :
41        ogg.ogg_stream_clear(&self._stream)
42        ogg.theora_info_clear(&self._info)
43        ogg.theora_comment_clear(&self._comment)
44        ogg.theora_clear(&self._decode)
45      return 0
46    _page = <ogg.ogg_page*> _data
47    #
48    # For Chaining/Looping
49    if ogg.ogg_page_bos(_page) :
50      if self._stage > 0 :
51        ogg.ogg_stream_clear(&self._stream)
52        ogg.theora_info_clear(&self._info)
53        ogg.theora_comment_clear(&self._comment)
54        ogg.theora_clear(&self._decode)
55        self._startTime = self._startTime + self._frameTime
56        self._frameTime = 0
57      else :
58        self._startTime = _time()
59      self._stage = 0
60    #
61    # Read Page 0
62    if self._stage == 0 :
63      ogg.ogg_stream_init(&self._stream, ogg.ogg_page_serialno(_page))
64      ogg.theora_info_init(&self._info)
65      ogg.theora_comment_init(&self._comment)
66      self._stage = 1
67    # Read in the page if not -1
68    if self._stage > 0 :
69      ogg.ogg_stream_pagein(&self._stream, _page)
70    # Read pre-data pages (if any)
71    if self._stage == 1 :
72      if ogg.ogg_page_granulepos(_page) == 0 :
73        while ogg.ogg_stream_packetout(&self._stream, &_packet) :
74          if ogg.theora_decode_header(&self._info, &self._comment,&_packet)<0 :
75            # Error in header, clear what we've setup and bail
76            ogg.ogg_stream_clear(&self._stream)
77            ogg.theora_info_clear(&self._info)
78            ogg.theora_comment_clear(&self._comment)
79            self._stage = -1
80            return 0
81        if ogg.ogg_page_pageno(_page) == 0 :
82          #
83          # Resize for RGBX then set self._chans to RGB to ignore the X
84          self._resize(1, 4, self._squareup(self._info.frame_width),
85                          self._squareup(self._info.frame_height), 1)
86          self._chans = 3
87          self._scaleX = <float> self._info.frame_width  / <float> self._width
88          self._scaleY = <float> self._info.frame_height / <float> self._height
89          self._aspect = ( <float> self._info.frame_width / \
90                           <float> self._info.frame_height ) * \
91                         ( <float> self._info.aspect_numerator / \
92                           <float> self._info.aspect_denominator )
93      else :
94        ogg.theora_decode_init(&self._decode, &self._info)
95        self._stage = 2
96    if self._stage == 2 :
97      # Theora frames are 1:1 with Ogg packets, but packets != pages
98      while ogg.ogg_stream_packetout(&self._stream, &_packet) :
99        ogg.theora_decode_packetin(&self._decode, &_packet)
100        self._frameTime = ogg.theora_granule_time(&self._decode,
101                                              ogg.ogg_page_granulepos(_page))
102        ogg.theora_decode_YUVout(&self._decode, &_yuv)
103        #
104        # This can and should be optimized further
105        #_start = _time()
106        for _y from 0 <= _y < self._info.frame_height :
107          oil.oil_yuv2rgbx_sub2_u8(
108            self._texels + ((self._info.frame_height - _y) * self._width * 4),
109            _yuv.y + ( _y * _yuv.y_stride),
110            _yuv.u + ((_y / 2) * _yuv.uv_stride),
111            _yuv.v + ((_y / 2) * _yuv.uv_stride),
112            self._info.frame_width)
113        self._update = 1
114    return 1
115
116
117  cdef int _save(self, void *_data, int _size) nogil :
118    cdef ogg.ogg_page   *_page
119    _page = <ogg.ogg_page*> _data
120    return 1
121
122
123  cdef int _ready(self) nogil :
124    cdef double  _now
125    _now = _time()
126    if self._startTime + self._frameTime < _now :
127      return 1
128    return 0
129
130
131  ############################################################################
132  #
133  # Properties
134  #
135 
136  property offset :
137    def __get__(self) :
138      return self._frameTime
Note: See TracBrowser for help on using the repository browser.