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
RevLine 
[336]1# PySoy's textures.Video class
[214]2#
[1345]3# Copyright (C) 2006,2007,2008,2009 PySoy Group
[214]4#
5#  This program is free software; you can redistribute it and/or modify
[1144]6#  it under the terms of the GNU Affero General Public License as published
[1145]7#  by the Free Software Foundation, either version 3 of the License, or
[214]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
[1144]13#  GNU Affero General Public License for more details.
[214]14#
[1144]15#  You should have received a copy of the GNU Affero General Public License
[214]16#  along with this program; if not, see http://www.gnu.org/licenses
17#
[1359]18# $Id: Video.pym 1462 2009-01-11 05:26:23Z ArcRiley $
[390]19
[214]20
[336]21cdef class Video (Texture) :
22  '''PySoy textures.Video Class
[214]23
[868]24    Renders an Ogg Theora stream to a texture
[214]25  '''
[1129]26
[1166]27  ############################################################################
28  #
29  # C functions
30  #
31 
[1219]32  cdef int _load(self, void* _data, int _size) nogil :
[1359]33    cdef int             _y
[1129]34    cdef ogg.ogg_page*   _page
[351]35    cdef ogg.yuv_buffer  _yuv
[340]36    cdef ogg.ogg_packet  _packet
[389]37    cdef double          _start  # for benchmarking
[530]38    if _data == NULL :
[392]39      stdio.printf('done decoding.\n')
[351]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
[1102]46    _page = <ogg.ogg_page*> _data
[392]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 :
[629]58        self._startTime = _time()
[392]59      self._stage = 0
60    #
[382]61    # Read Page 0
[340]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
[382]67    # Read in the page if not -1
[340]68    if self._stage > 0 :
[382]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 :
[1359]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),
[382]85                          self._squareup(self._info.frame_height), 1)
[1359]86          self._chans = 3
[383]87          self._scaleX = <float> self._info.frame_width  / <float> self._width
88          self._scaleY = <float> self._info.frame_height / <float> self._height
[382]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 :
[340]94        ogg.theora_decode_init(&self._decode, &self._info)
95        self._stage = 2
96    if self._stage == 2 :
[351]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)
[386]100        self._frameTime = ogg.theora_granule_time(&self._decode,
101                                              ogg.ogg_page_granulepos(_page))
[351]102        ogg.theora_decode_YUVout(&self._decode, &_yuv)
[384]103        #
104        # This can and should be optimized further
[629]105        #_start = _time()
[1359]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)
[382]113        self._update = 1
[340]114    return 1
[336]115
[386]116
[1219]117  cdef int _save(self, void *_data, int _size) nogil :
[340]118    cdef ogg.ogg_page   *_page
[1102]119    _page = <ogg.ogg_page*> _data
[340]120    return 1
[386]121
[387]122
[1219]123  cdef int _ready(self) nogil :
[386]124    cdef double  _now
[629]125    _now = _time()
[388]126    if self._startTime + self._frameTime < _now :
[386]127      return 1
128    return 0
[387]129
[1219]130
[1166]131  ############################################################################
132  #
133  # Properties
134  #
135 
[387]136  property offset :
137    def __get__(self) :
138      return self._frameTime
Note: See TracBrowser for help on using the repository browser.