~ubuntu-branches/ubuntu/lucid/blender/lucid

« back to all changes in this revision

Viewing changes to source/gameengine/VideoTexture/VideoFFmpeg.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Chris Coulson
  • Date: 2009-08-06 22:32:19 UTC
  • mfrom: (1.2.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090806223219-8z4eej1u8levu4pz
Tags: 2.49a+dfsg-0ubuntu1
* Merge from debian unstable, remaining changes:
  - debian/control: Build-depend on python-2.6 rather than python-2.5.
  - debian/misc/*.desktop: Add Spanish translation to .desktop 
    files.
  - debian/pyversions: 2.6.
  - debian/rules: Clean *.o of source/blender/python/api2_2x/
* New upstream release (LP: #382153).
* Refreshed patches:
  - 01_sanitize_sys.patch
  - 02_tmp_in_HOME
  - 10_use_systemwide_ftgl
  - 70_portability_platform_detection
* Removed patches merged upstream:
  - 30_fix_python_syntax_warning
  - 90_ubuntu_ffmpeg_52_changes

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: VideoFFmpeg.cpp 20689 2009-06-06 21:54:12Z ben2610 $
 
2
-----------------------------------------------------------------------------
 
3
This source file is part of VideoTexture library
 
4
 
 
5
Copyright (c) 2007 The Zdeno Ash Miklas
 
6
 
 
7
This program is free software; you can redistribute it and/or modify it under
 
8
the terms of the GNU Lesser General Public License as published by the Free Software
 
9
Foundation; either version 2 of the License, or (at your option) any later
 
10
version.
 
11
 
 
12
This program is distributed in the hope that it will be useful, but WITHOUT
 
13
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
14
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 
15
 
 
16
You should have received a copy of the GNU Lesser General Public License along with
 
17
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
18
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
 
19
http://www.gnu.org/copyleft/lesser.txt.
 
20
-----------------------------------------------------------------------------
 
21
*/
 
22
 
 
23
#ifdef WITH_FFMPEG
 
24
 
 
25
// INT64_C fix for some linux machines (C99ism)
 
26
#define __STDC_CONSTANT_MACROS
 
27
#include <stdint.h>
 
28
 
 
29
 
 
30
#include "MEM_guardedalloc.h"
 
31
#include "PIL_time.h"
 
32
 
 
33
#include <string>
 
34
 
 
35
#include "Exception.h"
 
36
#include "VideoFFmpeg.h"
 
37
 
 
38
 
 
39
// default framerate
 
40
const double defFrameRate = 25.0;
 
41
// time scale constant
 
42
const long timeScale = 1000;
 
43
 
 
44
// macro for exception handling and logging
 
45
#define CATCH_EXCP catch (Exception & exp) \
 
46
{ exp.report(); m_status = SourceError; }
 
47
 
 
48
extern "C" void do_init_ffmpeg();
 
49
 
 
50
// class RenderVideo
 
51
 
 
52
// constructor
 
53
VideoFFmpeg::VideoFFmpeg (HRESULT * hRslt) : VideoBase(), 
 
54
m_codec(NULL), m_formatCtx(NULL), m_codecCtx(NULL), 
 
55
m_frame(NULL), m_frameDeinterlaced(NULL), m_frameRGB(NULL), m_imgConvertCtx(NULL),
 
56
m_deinterlace(false), m_preseek(0),     m_videoStream(-1), m_baseFrameRate(25.0),
 
57
m_lastFrame(-1),  m_eof(false), m_curPosition(-1), m_startTime(0), 
 
58
m_captWidth(0), m_captHeight(0), m_captRate(0.f), m_isImage(false),
 
59
m_isThreaded(false), m_stopThread(false), m_cacheStarted(false)
 
60
{
 
61
        // set video format
 
62
        m_format = RGB24;
 
63
        // force flip because ffmpeg always return the image in the wrong orientation for texture
 
64
        setFlip(true);
 
65
        // construction is OK
 
66
        *hRslt = S_OK;
 
67
        m_thread.first = m_thread.last = NULL;
 
68
        pthread_mutex_init(&m_cacheMutex, NULL);
 
69
        m_frameCacheFree.first = m_frameCacheFree.last = NULL;
 
70
        m_frameCacheBase.first = m_frameCacheBase.last = NULL;
 
71
        m_packetCacheFree.first = m_packetCacheFree.last = NULL;
 
72
        m_packetCacheBase.first = m_packetCacheBase.last = NULL;
 
73
}
 
74
 
 
75
// destructor
 
76
VideoFFmpeg::~VideoFFmpeg () 
 
77
{
 
78
}
 
79
 
 
80
 
 
81
// release components
 
82
bool VideoFFmpeg::release()
 
83
{
 
84
        // release
 
85
        stopCache();
 
86
        if (m_codecCtx)
 
87
        {
 
88
                avcodec_close(m_codecCtx);
 
89
                m_codecCtx = NULL;
 
90
        }
 
91
        if (m_formatCtx)
 
92
        {
 
93
                av_close_input_file(m_formatCtx);
 
94
                m_formatCtx = NULL;
 
95
        }
 
96
        if (m_frame)
 
97
        {
 
98
                av_free(m_frame);
 
99
                m_frame = NULL;
 
100
        }
 
101
        if (m_frameDeinterlaced)
 
102
        {
 
103
                MEM_freeN(m_frameDeinterlaced->data[0]);
 
104
                av_free(m_frameDeinterlaced);
 
105
                m_frameDeinterlaced = NULL;
 
106
        }
 
107
        if (m_frameRGB)
 
108
        {
 
109
                MEM_freeN(m_frameRGB->data[0]);
 
110
                av_free(m_frameRGB);
 
111
                m_frameRGB = NULL;
 
112
        }
 
113
        if (m_imgConvertCtx)
 
114
        {
 
115
                sws_freeContext(m_imgConvertCtx);
 
116
                m_imgConvertCtx = NULL;
 
117
        }
 
118
        m_codec = NULL;
 
119
        m_status = SourceStopped;
 
120
        m_lastFrame = -1;
 
121
        return true;
 
122
}
 
123
 
 
124
AVFrame *VideoFFmpeg::allocFrameRGB()
 
125
{
 
126
        AVFrame *frame;
 
127
        frame = avcodec_alloc_frame();
 
128
        if (m_format == RGBA32)
 
129
        {
 
130
                avpicture_fill((AVPicture*)frame, 
 
131
                        (uint8_t*)MEM_callocN(avpicture_get_size(
 
132
                                PIX_FMT_RGBA,
 
133
                                m_codecCtx->width, m_codecCtx->height),
 
134
                                "ffmpeg rgba"),
 
135
                        PIX_FMT_RGBA, m_codecCtx->width, m_codecCtx->height);
 
136
        } else 
 
137
        {
 
138
                avpicture_fill((AVPicture*)frame, 
 
139
                        (uint8_t*)MEM_callocN(avpicture_get_size(
 
140
                                PIX_FMT_RGB24,
 
141
                                m_codecCtx->width, m_codecCtx->height),
 
142
                                "ffmpeg rgb"),
 
143
                        PIX_FMT_RGB24, m_codecCtx->width, m_codecCtx->height);
 
144
        }
 
145
        return frame;
 
146
}
 
147
 
 
148
// set initial parameters
 
149
void VideoFFmpeg::initParams (short width, short height, float rate, bool image)
 
150
{
 
151
        m_captWidth = width;
 
152
        m_captHeight = height;
 
153
        m_captRate = rate;
 
154
        m_isImage = image;
 
155
}
 
156
 
 
157
 
 
158
int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AVFormatParameters *formatParams)
 
159
{
 
160
        AVFormatContext *formatCtx;
 
161
        int                             i, videoStream;
 
162
        AVCodec                 *codec;
 
163
        AVCodecContext  *codecCtx;
 
164
 
 
165
        if(av_open_input_file(&formatCtx, filename, inputFormat, 0, formatParams)!=0)
 
166
                return -1;
 
167
 
 
168
        if(av_find_stream_info(formatCtx)<0) 
 
169
        {
 
170
                av_close_input_file(formatCtx);
 
171
                return -1;
 
172
        }
 
173
 
 
174
        /* Find the first video stream */
 
175
        videoStream=-1;
 
176
        for(i=0; i<formatCtx->nb_streams; i++)
 
177
        {
 
178
                if(formatCtx->streams[i] &&
 
179
                        get_codec_from_stream(formatCtx->streams[i]) && 
 
180
                        (get_codec_from_stream(formatCtx->streams[i])->codec_type==CODEC_TYPE_VIDEO))
 
181
                {
 
182
                        videoStream=i;
 
183
                        break;
 
184
                }
 
185
        }
 
186
 
 
187
        if(videoStream==-1) 
 
188
        {
 
189
                av_close_input_file(formatCtx);
 
190
                return -1;
 
191
        }
 
192
 
 
193
        codecCtx = get_codec_from_stream(formatCtx->streams[videoStream]);
 
194
 
 
195
        /* Find the decoder for the video stream */
 
196
        codec=avcodec_find_decoder(codecCtx->codec_id);
 
197
        if(codec==NULL) 
 
198
        {
 
199
                av_close_input_file(formatCtx);
 
200
                return -1;
 
201
        }
 
202
        codecCtx->workaround_bugs = 1;
 
203
        if(avcodec_open(codecCtx, codec)<0) 
 
204
        {
 
205
                av_close_input_file(formatCtx);
 
206
                return -1;
 
207
        }
 
208
 
 
209
#ifdef FFMPEG_OLD_FRAME_RATE
 
210
        if(codecCtx->frame_rate>1000 && codecCtx->frame_rate_base==1)
 
211
                codecCtx->frame_rate_base=1000;
 
212
        m_baseFrameRate = (double)codecCtx->frame_rate / (double)codecCtx->frame_rate_base;
 
213
#else
 
214
        m_baseFrameRate = av_q2d(formatCtx->streams[videoStream]->r_frame_rate);
 
215
#endif
 
216
        if (m_baseFrameRate <= 0.0) 
 
217
                m_baseFrameRate = defFrameRate;
 
218
 
 
219
        m_codec = codec;
 
220
        m_codecCtx = codecCtx;
 
221
        m_formatCtx = formatCtx;
 
222
        m_videoStream = videoStream;
 
223
        m_frame = avcodec_alloc_frame();
 
224
        m_frameDeinterlaced = avcodec_alloc_frame();
 
225
 
 
226
        // allocate buffer if deinterlacing is required
 
227
        avpicture_fill((AVPicture*)m_frameDeinterlaced, 
 
228
                (uint8_t*)MEM_callocN(avpicture_get_size(
 
229
                m_codecCtx->pix_fmt,
 
230
                m_codecCtx->width, m_codecCtx->height), 
 
231
                "ffmpeg deinterlace"), 
 
232
                m_codecCtx->pix_fmt, m_codecCtx->width, m_codecCtx->height);
 
233
 
 
234
        // check if the pixel format supports Alpha
 
235
        if (m_codecCtx->pix_fmt == PIX_FMT_RGB32 ||
 
236
                m_codecCtx->pix_fmt == PIX_FMT_BGR32 ||
 
237
                m_codecCtx->pix_fmt == PIX_FMT_RGB32_1 ||
 
238
                m_codecCtx->pix_fmt == PIX_FMT_BGR32_1) 
 
239
        {
 
240
                // allocate buffer to store final decoded frame
 
241
                m_format = RGBA32;
 
242
                // allocate sws context
 
243
                m_imgConvertCtx = sws_getContext(
 
244
                        m_codecCtx->width,
 
245
                        m_codecCtx->height,
 
246
                        m_codecCtx->pix_fmt,
 
247
                        m_codecCtx->width,
 
248
                        m_codecCtx->height,
 
249
                        PIX_FMT_RGBA,
 
250
                        SWS_FAST_BILINEAR,
 
251
                        NULL, NULL, NULL);
 
252
        } else
 
253
        {
 
254
                // allocate buffer to store final decoded frame
 
255
                m_format = RGB24;
 
256
                // allocate sws context
 
257
                m_imgConvertCtx = sws_getContext(
 
258
                        m_codecCtx->width,
 
259
                        m_codecCtx->height,
 
260
                        m_codecCtx->pix_fmt,
 
261
                        m_codecCtx->width,
 
262
                        m_codecCtx->height,
 
263
                        PIX_FMT_RGB24,
 
264
                        SWS_FAST_BILINEAR,
 
265
                        NULL, NULL, NULL);
 
266
        }
 
267
        m_frameRGB = allocFrameRGB();
 
268
 
 
269
        if (!m_imgConvertCtx) {
 
270
                avcodec_close(m_codecCtx);
 
271
                m_codecCtx = NULL;
 
272
                av_close_input_file(m_formatCtx);
 
273
                m_formatCtx = NULL;
 
274
                av_free(m_frame);
 
275
                m_frame = NULL;
 
276
                MEM_freeN(m_frameDeinterlaced->data[0]);
 
277
                av_free(m_frameDeinterlaced);
 
278
                m_frameDeinterlaced = NULL;
 
279
                MEM_freeN(m_frameRGB->data[0]);
 
280
                av_free(m_frameRGB);
 
281
                m_frameRGB = NULL;
 
282
                return -1;
 
283
        }
 
284
        return 0;
 
285
}
 
286
 
 
287
/*
 
288
 * This thread is used to load video frame asynchronously.
 
289
 * It provides a frame caching service. 
 
290
 * The main thread is responsible for positionning the frame pointer in the
 
291
 * file correctly before calling startCache() which starts this thread.
 
292
 * The cache is organized in two layers: 1) a cache of 20-30 undecoded packets to keep
 
293
 * memory and CPU low 2) a cache of 5 decoded frames. 
 
294
 * If the main thread does not find the frame in the cache (because the video has restarted
 
295
 * or because the GE is lagging), it stops the cache with StopCache() (this is a synchronous
 
296
 * function: it sends a signal to stop the cache thread and wait for confirmation), then
 
297
 * change the position in the stream and restarts the cache thread.
 
298
 */
 
299
void *VideoFFmpeg::cacheThread(void *data)
 
300
{
 
301
        VideoFFmpeg* video = (VideoFFmpeg*)data;
 
302
        // holds the frame that is being decoded
 
303
        CacheFrame *currentFrame = NULL;
 
304
        CachePacket *cachePacket;
 
305
        bool endOfFile = false;
 
306
        int frameFinished = 0;
 
307
 
 
308
        while (!video->m_stopThread)
 
309
        {
 
310
                // packet cache is used solely by this thread, no need to lock
 
311
                // In case the stream/file contains other stream than the one we are looking for,
 
312
                // allow a bit of cycling to get rid quickly of those frames
 
313
                frameFinished = 0;
 
314
                while (    !endOfFile 
 
315
                                && (cachePacket = (CachePacket *)video->m_packetCacheFree.first) != NULL 
 
316
                                && frameFinished < 25)
 
317
                {
 
318
                        // free packet => packet cache is not full yet, just read more
 
319
                        if (av_read_frame(video->m_formatCtx, &cachePacket->packet)>=0) 
 
320
                        {
 
321
                                if (cachePacket->packet.stream_index == video->m_videoStream)
 
322
                                {
 
323
                                        // make sure fresh memory is allocated for the packet and move it to queue
 
324
                                        av_dup_packet(&cachePacket->packet);
 
325
                                        BLI_remlink(&video->m_packetCacheFree, cachePacket);
 
326
                                        BLI_addtail(&video->m_packetCacheBase, cachePacket);
 
327
                                        break;
 
328
                                } else {
 
329
                                        // this is not a good packet for us, just leave it on free queue
 
330
                                        // Note: here we could handle sound packet
 
331
                                        av_free_packet(&cachePacket->packet);
 
332
                                        frameFinished++;
 
333
                                }
 
334
                                
 
335
                        } else {
 
336
                                if (video->m_isFile)
 
337
                                        // this mark the end of the file
 
338
                                        endOfFile = true;
 
339
                                // if we cannot read a packet, no need to continue
 
340
                                break;
 
341
                        }
 
342
                }
 
343
                // frame cache is also used by main thread, lock
 
344
                if (currentFrame == NULL) 
 
345
                {
 
346
                        // no current frame being decoded, take free one
 
347
                        pthread_mutex_lock(&video->m_cacheMutex);
 
348
                        if ((currentFrame = (CacheFrame *)video->m_frameCacheFree.first) != NULL)
 
349
                                BLI_remlink(&video->m_frameCacheFree, currentFrame);
 
350
                        pthread_mutex_unlock(&video->m_cacheMutex);
 
351
                }
 
352
                if (currentFrame != NULL)
 
353
                {
 
354
                        // this frame is out of free and busy queue, we can manipulate it without locking
 
355
                        frameFinished = 0;
 
356
                        while (!frameFinished && (cachePacket = (CachePacket *)video->m_packetCacheBase.first) != NULL)
 
357
                        {
 
358
                                BLI_remlink(&video->m_packetCacheBase, cachePacket);
 
359
                                // use m_frame because when caching, it is not used in main thread
 
360
                                // we can't use currentFrame directly because we need to convert to RGB first
 
361
                                avcodec_decode_video(video->m_codecCtx, 
 
362
                                        video->m_frame, &frameFinished, 
 
363
                                        cachePacket->packet.data, cachePacket->packet.size);
 
364
                                if(frameFinished) 
 
365
                                {
 
366
                                        AVFrame * input = video->m_frame;
 
367
 
 
368
                                        /* This means the data wasnt read properly, this check stops crashing */
 
369
                                        if (   input->data[0]!=0 || input->data[1]!=0 
 
370
                                                || input->data[2]!=0 || input->data[3]!=0)
 
371
                                        {
 
372
                                                if (video->m_deinterlace) 
 
373
                                                {
 
374
                                                        if (avpicture_deinterlace(
 
375
                                                                (AVPicture*) video->m_frameDeinterlaced,
 
376
                                                                (const AVPicture*) video->m_frame,
 
377
                                                                video->m_codecCtx->pix_fmt,
 
378
                                                                video->m_codecCtx->width,
 
379
                                                                video->m_codecCtx->height) >= 0)
 
380
                                                        {
 
381
                                                                input = video->m_frameDeinterlaced;
 
382
                                                        }
 
383
                                                }
 
384
                                                // convert to RGB24
 
385
                                                sws_scale(video->m_imgConvertCtx,
 
386
                                                        input->data,
 
387
                                                        input->linesize,
 
388
                                                        0,
 
389
                                                        video->m_codecCtx->height,
 
390
                                                        currentFrame->frame->data,
 
391
                                                        currentFrame->frame->linesize);
 
392
                                                // move frame to queue, this frame is necessarily the next one
 
393
                                                currentFrame->framePosition = ++video->m_curPosition;
 
394
                                                pthread_mutex_lock(&video->m_cacheMutex);
 
395
                                                BLI_addtail(&video->m_frameCacheBase, currentFrame);
 
396
                                                pthread_mutex_unlock(&video->m_cacheMutex);
 
397
                                                currentFrame = NULL;
 
398
                                        }
 
399
                                }
 
400
                                av_free_packet(&cachePacket->packet);
 
401
                                BLI_addtail(&video->m_packetCacheFree, cachePacket);
 
402
                        } 
 
403
                        if (currentFrame && endOfFile) 
 
404
                        {
 
405
                                // no more packet and end of file => put a special frame that indicates that
 
406
                                currentFrame->framePosition = -1;
 
407
                                pthread_mutex_lock(&video->m_cacheMutex);
 
408
                                BLI_addtail(&video->m_frameCacheBase, currentFrame);
 
409
                                pthread_mutex_unlock(&video->m_cacheMutex);
 
410
                                currentFrame = NULL;
 
411
                                // no need to stay any longer in this thread
 
412
                                break;
 
413
                        }
 
414
                }
 
415
                // small sleep to avoid unnecessary looping
 
416
                PIL_sleep_ms(10);
 
417
        }
 
418
        // before quitting, put back the current frame to queue to allow freeing
 
419
        if (currentFrame)
 
420
        {
 
421
                pthread_mutex_lock(&video->m_cacheMutex);
 
422
                BLI_addtail(&video->m_frameCacheFree, currentFrame);
 
423
                pthread_mutex_unlock(&video->m_cacheMutex);
 
424
        }
 
425
        return 0;
 
426
}
 
427
 
 
428
// start thread to cache video frame from file/capture/stream
 
429
// this function should be called only when the position in the stream is set for the
 
430
// first frame to cache
 
431
bool VideoFFmpeg::startCache()
 
432
{
 
433
        if (!m_cacheStarted && m_isThreaded)
 
434
        {
 
435
                m_stopThread = false;
 
436
                for (int i=0; i<CACHE_FRAME_SIZE; i++)
 
437
                {
 
438
                        CacheFrame *frame = new CacheFrame();
 
439
                        frame->frame = allocFrameRGB();
 
440
                        BLI_addtail(&m_frameCacheFree, frame);
 
441
                }
 
442
                for (int i=0; i<CACHE_PACKET_SIZE; i++) 
 
443
                {
 
444
                        CachePacket *packet = new CachePacket();
 
445
                        BLI_addtail(&m_packetCacheFree, packet);
 
446
                }
 
447
                BLI_init_threads(&m_thread, cacheThread, 1);
 
448
                BLI_insert_thread(&m_thread, this);
 
449
                m_cacheStarted = true;
 
450
        }
 
451
        return m_cacheStarted;
 
452
}
 
453
 
 
454
void VideoFFmpeg::stopCache()
 
455
{
 
456
        if (m_cacheStarted)
 
457
        {
 
458
                m_stopThread = true;
 
459
                BLI_end_threads(&m_thread);
 
460
                // now delete the cache
 
461
                CacheFrame *frame;
 
462
                CachePacket *packet;
 
463
                while ((frame = (CacheFrame *)m_frameCacheBase.first) != NULL)
 
464
                {
 
465
                        BLI_remlink(&m_frameCacheBase, frame);
 
466
                        MEM_freeN(frame->frame->data[0]);
 
467
                        av_free(frame->frame);
 
468
                        delete frame;
 
469
                }
 
470
                while ((frame = (CacheFrame *)m_frameCacheFree.first) != NULL)
 
471
                {
 
472
                        BLI_remlink(&m_frameCacheFree, frame);
 
473
                        MEM_freeN(frame->frame->data[0]);
 
474
                        av_free(frame->frame);
 
475
                        delete frame;
 
476
                }
 
477
                while((packet = (CachePacket *)m_packetCacheBase.first) != NULL)
 
478
                {
 
479
                        BLI_remlink(&m_packetCacheBase, packet);
 
480
                        av_free_packet(&packet->packet);
 
481
                        delete packet;
 
482
                }
 
483
                while((packet = (CachePacket *)m_packetCacheFree.first) != NULL)
 
484
                {
 
485
                        BLI_remlink(&m_packetCacheFree, packet);
 
486
                        delete packet;
 
487
                }
 
488
                m_cacheStarted = false;
 
489
        }
 
490
}
 
491
 
 
492
void VideoFFmpeg::releaseFrame(AVFrame* frame)
 
493
{
 
494
        if (frame == m_frameRGB)
 
495
        {
 
496
                // this is not a frame from the cache, ignore
 
497
                return;
 
498
        }
 
499
        // this frame MUST be the first one of the queue
 
500
        pthread_mutex_lock(&m_cacheMutex);
 
501
        CacheFrame *cacheFrame = (CacheFrame *)m_frameCacheBase.first;
 
502
        assert (cacheFrame != NULL && cacheFrame->frame == frame);
 
503
        BLI_remlink(&m_frameCacheBase, cacheFrame);
 
504
        BLI_addtail(&m_frameCacheFree, cacheFrame);
 
505
        pthread_mutex_unlock(&m_cacheMutex);
 
506
}
 
507
 
 
508
// open video file
 
509
void VideoFFmpeg::openFile (char * filename)
 
510
{
 
511
        do_init_ffmpeg();
 
512
 
 
513
        if (openStream(filename, NULL, NULL) != 0)
 
514
                return;
 
515
 
 
516
        if (m_codecCtx->gop_size)
 
517
                m_preseek = (m_codecCtx->gop_size < 25) ? m_codecCtx->gop_size+1 : 25;
 
518
        else if (m_codecCtx->has_b_frames)              
 
519
                m_preseek = 25; // should determine gopsize
 
520
        else
 
521
                m_preseek = 0;
 
522
 
 
523
        // get video time range
 
524
        m_range[0] = 0.0;
 
525
        m_range[1] = (double)m_formatCtx->duration / AV_TIME_BASE;
 
526
 
 
527
        // open base class
 
528
        VideoBase::openFile(filename);
 
529
 
 
530
        if (
 
531
                // ffmpeg reports that http source are actually non stream
 
532
                // but it is really not desirable to seek on http file, so force streaming.
 
533
                // It would be good to find this information from the context but there are no simple indication
 
534
                !strncmp(filename, "http://", 7) ||
 
535
#ifdef FFMPEG_PB_IS_POINTER
 
536
        (m_formatCtx->pb && m_formatCtx->pb->is_streamed)
 
537
#else
 
538
        m_formatCtx->pb.is_streamed
 
539
#endif
 
540
        )
 
541
        {
 
542
                // the file is in fact a streaming source, prevent seeking
 
543
                m_isFile = false;
 
544
                // for streaming it is important to do non blocking read
 
545
                m_formatCtx->flags |= AVFMT_FLAG_NONBLOCK;
 
546
        }
 
547
 
 
548
        if (m_isImage) 
 
549
        {
 
550
                // the file is to be treated as an image, i.e. load the first frame only
 
551
                m_isFile = false;
 
552
                // in case of reload, the filename is taken from m_imageName, no need to change it
 
553
                if (m_imageName.Ptr() != filename)
 
554
                        m_imageName = filename;
 
555
                m_preseek = 0;
 
556
                m_avail = false;
 
557
                play();
 
558
        }
 
559
        // check if we should do multi-threading?
 
560
        if (!m_isImage && BLI_system_thread_count() > 1)
 
561
        {
 
562
                // never thread image: there are no frame to read ahead
 
563
                // no need to thread if the system has a single core
 
564
                m_isThreaded =  true;
 
565
        }
 
566
}
 
567
 
 
568
 
 
569
// open video capture device
 
570
void VideoFFmpeg::openCam (char * file, short camIdx)
 
571
{
 
572
        // open camera source
 
573
        AVInputFormat           *inputFormat;
 
574
        AVFormatParameters      formatParams;
 
575
        AVRational                      frameRate;
 
576
        char                            *p, filename[28], rateStr[20];
 
577
 
 
578
        do_init_ffmpeg();
 
579
 
 
580
        memset(&formatParams, 0, sizeof(formatParams));
 
581
#ifdef WIN32
 
582
        // video capture on windows only through Video For Windows driver
 
583
        inputFormat = av_find_input_format("vfwcap");
 
584
        if (!inputFormat)
 
585
                // Video For Windows not supported??
 
586
                return;
 
587
        sprintf(filename, "%d", camIdx);
 
588
#else
 
589
        // In Linux we support two types of devices: VideoForLinux and DV1394. 
 
590
        // the user specify it with the filename:
 
591
        // [<device_type>][:<standard>]
 
592
        // <device_type> : 'v4l' for VideoForLinux, 'dv1394' for DV1394. By default 'v4l'
 
593
        // <standard>    : 'pal', 'secam' or 'ntsc'. By default 'ntsc'
 
594
        // The driver name is constructed automatically from the device type:
 
595
        // v4l   : /dev/video<camIdx>
 
596
        // dv1394: /dev/dv1394/<camIdx>
 
597
        // If you have different driver name, you can specify the driver name explicitely 
 
598
        // instead of device type. Examples of valid filename:
 
599
        //    /dev/v4l/video0:pal
 
600
        //    /dev/ieee1394/1:ntsc
 
601
        //    dv1394:secam
 
602
        //    v4l:pal
 
603
        if (file && strstr(file, "1394") != NULL) 
 
604
        {
 
605
                // the user specifies a driver, check if it is v4l or d41394
 
606
                inputFormat = av_find_input_format("dv1394");
 
607
                sprintf(filename, "/dev/dv1394/%d", camIdx);
 
608
        } else 
 
609
        {
 
610
                inputFormat = av_find_input_format("video4linux");
 
611
                sprintf(filename, "/dev/video%d", camIdx);
 
612
        }
 
613
        if (!inputFormat)
 
614
                // these format should be supported, check ffmpeg compilation
 
615
                return;
 
616
        if (file && strncmp(file, "/dev", 4) == 0) 
 
617
        {
 
618
                // user does not specify a driver
 
619
                strncpy(filename, file, sizeof(filename));
 
620
                filename[sizeof(filename)-1] = 0;
 
621
                if ((p = strchr(filename, ':')) != 0)
 
622
                        *p = 0;
 
623
        }
 
624
        if (file && (p = strchr(file, ':')) != NULL)
 
625
                formatParams.standard = p+1;
 
626
#endif
 
627
        //frame rate
 
628
        if (m_captRate <= 0.f)
 
629
                m_captRate = defFrameRate;
 
630
        sprintf(rateStr, "%f", m_captRate);
 
631
        av_parse_video_frame_rate(&frameRate, rateStr);
 
632
        // populate format parameters
 
633
        // need to specify the time base = inverse of rate
 
634
        formatParams.time_base.num = frameRate.den;
 
635
        formatParams.time_base.den = frameRate.num;
 
636
        formatParams.width = m_captWidth;
 
637
        formatParams.height = m_captHeight;
 
638
 
 
639
        if (openStream(filename, inputFormat, &formatParams) != 0)
 
640
                return;
 
641
 
 
642
        // for video capture it is important to do non blocking read
 
643
        m_formatCtx->flags |= AVFMT_FLAG_NONBLOCK;
 
644
        // open base class
 
645
        VideoBase::openCam(file, camIdx);
 
646
        // check if we should do multi-threading?
 
647
        if (BLI_system_thread_count() > 1)
 
648
        {
 
649
                // no need to thread if the system has a single core
 
650
                m_isThreaded =  true;
 
651
        }
 
652
}
 
653
 
 
654
// play video
 
655
bool VideoFFmpeg::play (void)
 
656
{
 
657
        try
 
658
        {
 
659
                // if object is able to play
 
660
                if (VideoBase::play())
 
661
                {
 
662
                        // set video position
 
663
                        setPositions();
 
664
                        // return success
 
665
                        return true;
 
666
                }
 
667
        }
 
668
        CATCH_EXCP;
 
669
        return false;
 
670
}
 
671
 
 
672
 
 
673
// pause video
 
674
bool VideoFFmpeg::pause (void)
 
675
{
 
676
        try
 
677
        {
 
678
                if (VideoBase::pause())
 
679
                {
 
680
                        return true;
 
681
                }
 
682
        }
 
683
        CATCH_EXCP;
 
684
        return false;
 
685
}
 
686
 
 
687
// stop video
 
688
bool VideoFFmpeg::stop (void)
 
689
{
 
690
        try
 
691
        {
 
692
                VideoBase::stop();
 
693
                // force restart when play
 
694
                m_lastFrame = -1;
 
695
                return true;
 
696
        }
 
697
        CATCH_EXCP;
 
698
        return false;
 
699
}
 
700
 
 
701
 
 
702
// set video range
 
703
void VideoFFmpeg::setRange (double start, double stop)
 
704
{
 
705
        try
 
706
        {
 
707
                // set range
 
708
                if (m_isFile)
 
709
                {
 
710
                        VideoBase::setRange(start, stop);
 
711
                        // set range for video
 
712
                        setPositions();
 
713
                }
 
714
        }
 
715
        CATCH_EXCP;
 
716
}
 
717
 
 
718
// set framerate
 
719
void VideoFFmpeg::setFrameRate (float rate)
 
720
{
 
721
        VideoBase::setFrameRate(rate);
 
722
}
 
723
 
 
724
 
 
725
// image calculation
 
726
void VideoFFmpeg::calcImage (unsigned int texId)
 
727
{
 
728
        loadFrame();
 
729
}
 
730
 
 
731
 
 
732
// load frame from video
 
733
void VideoFFmpeg::loadFrame (void)
 
734
{
 
735
        if (m_status == SourcePlaying)
 
736
        {
 
737
                // get actual time
 
738
                double startTime = PIL_check_seconds_timer();
 
739
                if (m_lastFrame == -1 && !m_isFile)
 
740
                        m_startTime = startTime;
 
741
                double actTime = startTime - m_startTime;
 
742
                // if video has ended
 
743
                if (m_isFile && actTime * m_frameRate >= m_range[1])
 
744
                {
 
745
                        // in any case, this resets the cache
 
746
                        stopCache();
 
747
                        // if repeats are set, decrease them
 
748
                        if (m_repeat > 0) 
 
749
                                --m_repeat;
 
750
                        // if video has to be replayed
 
751
                        if (m_repeat != 0)
 
752
                        {
 
753
                                // reset its position
 
754
                                actTime -= (m_range[1] - m_range[0]) / m_frameRate;
 
755
                                m_startTime += (m_range[1] - m_range[0]) / m_frameRate;
 
756
                        }
 
757
                        // if video has to be stopped, stop it
 
758
                        else 
 
759
                        {
 
760
                                m_status = SourceStopped;
 
761
                                return;
 
762
                        }
 
763
                }
 
764
                // actual frame
 
765
                long actFrame = (m_isImage) ? m_lastFrame+1 : long(actTime * actFrameRate());
 
766
                // if actual frame differs from last frame
 
767
                if (actFrame != m_lastFrame)
 
768
                {
 
769
                        AVFrame* frame;
 
770
                        // get image
 
771
                        if((frame = grabFrame(actFrame)) != NULL)
 
772
                        {
 
773
                                if (!m_isFile && !m_cacheStarted) 
 
774
                                {
 
775
                                        // streaming without cache: detect synchronization problem
 
776
                                        double execTime = PIL_check_seconds_timer() - startTime;
 
777
                                        if (execTime > 0.005) 
 
778
                                        {
 
779
                                                // exec time is too long, it means that the function was blocking
 
780
                                                // resynchronize the stream from this time
 
781
                                                m_startTime += execTime;
 
782
                                        }
 
783
                                }
 
784
                                // save actual frame
 
785
                                m_lastFrame = actFrame;
 
786
                                // init image, if needed
 
787
                                init(short(m_codecCtx->width), short(m_codecCtx->height));
 
788
                                // process image
 
789
                                process((BYTE*)(frame->data[0]));
 
790
                                // finished with the frame, release it so that cache can reuse it
 
791
                                releaseFrame(frame);
 
792
                                // in case it is an image, automatically stop reading it
 
793
                                if (m_isImage)
 
794
                                {
 
795
                                        m_status = SourceStopped;
 
796
                                        // close the file as we don't need it anymore
 
797
                                        release();
 
798
                                }
 
799
                        } else if (!m_isFile)
 
800
                        {
 
801
                                // we didn't get a frame and we are streaming, this may be due to
 
802
                                // a delay in the network or because we are getting the frame too fast.
 
803
                                // In the later case, shift time by a small amount to compensate for a drift
 
804
                                m_startTime += 0.01;
 
805
                        }
 
806
                }
 
807
        }
 
808
}
 
809
 
 
810
 
 
811
// set actual position
 
812
void VideoFFmpeg::setPositions (void)
 
813
{
 
814
        // set video start time
 
815
        m_startTime = PIL_check_seconds_timer();
 
816
        // if file is played and actual position is before end position
 
817
        if (!m_eof && m_lastFrame >= 0 && (!m_isFile || m_lastFrame < m_range[1] * actFrameRate()))
 
818
                // continue from actual position
 
819
                m_startTime -= double(m_lastFrame) / actFrameRate();
 
820
        else {
 
821
                m_startTime -= m_range[0];
 
822
                // start from begining, stop cache just in case
 
823
                stopCache();
 
824
        }
 
825
}
 
826
 
 
827
// position pointer in file, position in second
 
828
AVFrame *VideoFFmpeg::grabFrame(long position)
 
829
{
 
830
        AVPacket packet;
 
831
        int frameFinished;
 
832
        int posFound = 1;
 
833
        bool frameLoaded = false;
 
834
        long long targetTs = 0;
 
835
        CacheFrame *frame;
 
836
 
 
837
        if (m_cacheStarted)
 
838
        {
 
839
                // when cache is active, we must not read the file directly
 
840
                do {
 
841
                        pthread_mutex_lock(&m_cacheMutex);
 
842
                        frame = (CacheFrame *)m_frameCacheBase.first;
 
843
                        pthread_mutex_unlock(&m_cacheMutex);
 
844
                        // no need to remove the frame from the queue: the cache thread does not touch the head, only the tail
 
845
                        if (frame == NULL)
 
846
                        {
 
847
                                // no frame in cache, in case of file it is an abnormal situation
 
848
                                if (m_isFile)
 
849
                                {
 
850
                                        // go back to no threaded reading
 
851
                                        stopCache();
 
852
                                        break;
 
853
                                }
 
854
                                return NULL;
 
855
                        }
 
856
                        if (frame->framePosition == -1) 
 
857
                        {
 
858
                                // this frame mark the end of the file (only used for file)
 
859
                                // leave in cache to make sure we don't miss it
 
860
                                m_eof = true;
 
861
                                return NULL;
 
862
                        }
 
863
                        // for streaming, always return the next frame, 
 
864
                        // that's what grabFrame does in non cache mode anyway.
 
865
                        if (!m_isFile || frame->framePosition == position)
 
866
                        {
 
867
                                return frame->frame;
 
868
                        }
 
869
                        // this frame is not useful, release it
 
870
                        pthread_mutex_lock(&m_cacheMutex);
 
871
                        BLI_remlink(&m_frameCacheBase, frame);
 
872
                        BLI_addtail(&m_frameCacheFree, frame);
 
873
                        pthread_mutex_unlock(&m_cacheMutex);
 
874
                } while (true);
 
875
        }
 
876
        // come here when there is no cache or cache has been stopped
 
877
        // locate the frame, by seeking if necessary (seeking is only possible for files)
 
878
        if (m_isFile)
 
879
        {
 
880
                // first check if the position that we are looking for is in the preseek range
 
881
                // if so, just read the frame until we get there
 
882
                if (position > m_curPosition + 1 
 
883
                        && m_preseek 
 
884
                        && position - (m_curPosition + 1) < m_preseek) 
 
885
                {
 
886
                        while(av_read_frame(m_formatCtx, &packet)>=0) 
 
887
                        {
 
888
                                if (packet.stream_index == m_videoStream) 
 
889
                                {
 
890
                                        avcodec_decode_video(
 
891
                                                m_codecCtx, 
 
892
                                                m_frame, &frameFinished, 
 
893
                                                packet.data, packet.size);
 
894
                                        if (frameFinished)
 
895
                                                m_curPosition++;
 
896
                                }
 
897
                                av_free_packet(&packet);
 
898
                                if (position == m_curPosition+1)
 
899
                                        break;
 
900
                        }
 
901
                }
 
902
                // if the position is not in preseek, do a direct jump
 
903
                if (position != m_curPosition + 1) 
 
904
                { 
 
905
                        double timeBase = av_q2d(m_formatCtx->streams[m_videoStream]->time_base);
 
906
                        int64_t pos = (int64_t)((position - m_preseek) / (m_baseFrameRate*timeBase));
 
907
                        int64_t startTs = m_formatCtx->streams[m_videoStream]->start_time;
 
908
                        int seekres;
 
909
 
 
910
                        if (pos < 0)
 
911
                                pos = 0;
 
912
 
 
913
                        if (startTs != AV_NOPTS_VALUE)
 
914
                                pos += startTs;
 
915
 
 
916
                        if (position <= m_curPosition || !m_eof)
 
917
                        {
 
918
#if 0
 
919
                                // Tried to make this work but couldn't: seeking on byte is ignored by the
 
920
                                // format plugin and it will generally continue to read from last timestamp.
 
921
                                // Too bad because frame seek is not always able to get the first frame
 
922
                                // of the file.
 
923
                                if (position <= m_preseek)
 
924
                                {
 
925
                                        // we can safely go the begining of the file
 
926
                                        if (av_seek_frame(m_formatCtx, m_videoStream, 0, AVSEEK_FLAG_BYTE) >= 0)
 
927
                                        {
 
928
                                                // binary seek does not reset the timestamp, must do it now
 
929
                                                av_update_cur_dts(m_formatCtx, m_formatCtx->streams[m_videoStream], startTs);
 
930
                                                m_curPosition = 0;
 
931
                                        }
 
932
                                }
 
933
                                else
 
934
#endif
 
935
                                {
 
936
                                        // current position is now lost, guess a value. 
 
937
                                        if (av_seek_frame(m_formatCtx, m_videoStream, pos, AVSEEK_FLAG_BACKWARD) >= 0)
 
938
                                        {
 
939
                                                // current position is now lost, guess a value. 
 
940
                                                // It's not important because it will be set at this end of this function
 
941
                                                m_curPosition = position - m_preseek - 1;
 
942
                                        }
 
943
                                }
 
944
                        }
 
945
                        // this is the timestamp of the frame we're looking for
 
946
                        targetTs = (int64_t)(position / (m_baseFrameRate * timeBase));
 
947
                        if (startTs != AV_NOPTS_VALUE)
 
948
                                targetTs += startTs;
 
949
 
 
950
                        posFound = 0;
 
951
                        avcodec_flush_buffers(m_codecCtx);
 
952
                }
 
953
        } else if (m_isThreaded)
 
954
        {
 
955
                // cache is not started but threading is possible
 
956
                // better not read the stream => make take some time, better start caching
 
957
                if (startCache())
 
958
                        return NULL;
 
959
                // Abnormal!!! could not start cache, fall back on direct read
 
960
                m_isThreaded = false;
 
961
        }
 
962
 
 
963
        // find the correct frame, in case of streaming and no cache, it means just
 
964
        // return the next frame. This is not quite correct, may need more work
 
965
        while(av_read_frame(m_formatCtx, &packet)>=0) 
 
966
        {
 
967
                if(packet.stream_index == m_videoStream) 
 
968
                {
 
969
                        avcodec_decode_video(m_codecCtx, 
 
970
                                m_frame, &frameFinished, 
 
971
                                packet.data, packet.size);
 
972
 
 
973
                        if (frameFinished && !posFound) 
 
974
                        {
 
975
                                if (packet.dts >= targetTs)
 
976
                                        posFound = 1;
 
977
                        } 
 
978
 
 
979
                        if(frameFinished && posFound == 1) 
 
980
                        {
 
981
                                AVFrame * input = m_frame;
 
982
 
 
983
                                /* This means the data wasnt read properly, 
 
984
                                this check stops crashing */
 
985
                                if (   input->data[0]==0 && input->data[1]==0 
 
986
                                        && input->data[2]==0 && input->data[3]==0)
 
987
                                {
 
988
                                        av_free_packet(&packet);
 
989
                                        break;
 
990
                                }
 
991
 
 
992
                                if (m_deinterlace) 
 
993
                                {
 
994
                                        if (avpicture_deinterlace(
 
995
                                                (AVPicture*) m_frameDeinterlaced,
 
996
                                                (const AVPicture*) m_frame,
 
997
                                                m_codecCtx->pix_fmt,
 
998
                                                m_codecCtx->width,
 
999
                                                m_codecCtx->height) >= 0)
 
1000
                                        {
 
1001
                                                input = m_frameDeinterlaced;
 
1002
                                        }
 
1003
                                }
 
1004
                                // convert to RGB24
 
1005
                                sws_scale(m_imgConvertCtx,
 
1006
                                        input->data,
 
1007
                                        input->linesize,
 
1008
                                        0,
 
1009
                                        m_codecCtx->height,
 
1010
                                        m_frameRGB->data,
 
1011
                                        m_frameRGB->linesize);
 
1012
                                av_free_packet(&packet);
 
1013
                                frameLoaded = true;
 
1014
                                break;
 
1015
                        }
 
1016
                }
 
1017
                av_free_packet(&packet);
 
1018
        }
 
1019
        m_eof = m_isFile && !frameLoaded;
 
1020
        if (frameLoaded)
 
1021
        {
 
1022
                m_curPosition = position;
 
1023
                if (m_isThreaded)
 
1024
                {
 
1025
                        // normal case for file: first locate, then start cache
 
1026
                        if (!startCache())
 
1027
                        {
 
1028
                                // Abnormal!! could not start cache, return to non-cache mode
 
1029
                                m_isThreaded = false;
 
1030
                        }
 
1031
                }
 
1032
                return m_frameRGB;
 
1033
        }
 
1034
        return NULL;
 
1035
}
 
1036
 
 
1037
 
 
1038
// python methods
 
1039
 
 
1040
 
 
1041
// cast Image pointer to VideoFFmpeg
 
1042
inline VideoFFmpeg * getVideoFFmpeg (PyImage * self)
 
1043
{ return static_cast<VideoFFmpeg*>(self->m_image); }
 
1044
 
 
1045
 
 
1046
// object initialization
 
1047
static int VideoFFmpeg_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
 
1048
{
 
1049
        PyImage * self = reinterpret_cast<PyImage*>(pySelf);
 
1050
        // parameters - video source
 
1051
        // file name or format type for capture (only for Linux: video4linux or dv1394)
 
1052
        char * file = NULL;
 
1053
        // capture device number
 
1054
        short capt = -1;
 
1055
        // capture width, only if capt is >= 0
 
1056
        short width = 0;
 
1057
        // capture height, only if capt is >= 0
 
1058
        short height = 0;
 
1059
        // capture rate, only if capt is >= 0
 
1060
        float rate = 25.f;
 
1061
 
 
1062
        static char *kwlist[] = {"file", "capture", "rate", "width", "height", NULL};
 
1063
 
 
1064
        // get parameters
 
1065
        if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|hfhh", kwlist, &file, &capt,
 
1066
                &rate, &width, &height))
 
1067
                return -1; 
 
1068
 
 
1069
        try
 
1070
        {
 
1071
                // create video object
 
1072
                Video_init<VideoFFmpeg>(self);
 
1073
 
 
1074
                // set thread usage
 
1075
                getVideoFFmpeg(self)->initParams(width, height, rate);
 
1076
 
 
1077
                // open video source
 
1078
                Video_open(getVideo(self), file, capt);
 
1079
        }
 
1080
        catch (Exception & exp)
 
1081
        {
 
1082
                exp.report();
 
1083
                return -1;
 
1084
        }
 
1085
        // initialization succeded
 
1086
        return 0;
 
1087
}
 
1088
 
 
1089
PyObject * VideoFFmpeg_getPreseek (PyImage *self, void * closure)
 
1090
{
 
1091
        return Py_BuildValue("h", getFFmpeg(self)->getPreseek());
 
1092
}
 
1093
 
 
1094
// set range
 
1095
int VideoFFmpeg_setPreseek (PyImage * self, PyObject * value, void * closure)
 
1096
{
 
1097
        // check validity of parameter
 
1098
        if (value == NULL || !PyInt_Check(value))
 
1099
        {
 
1100
                PyErr_SetString(PyExc_TypeError, "The value must be an integer");
 
1101
                return -1;
 
1102
        }
 
1103
        // set preseek
 
1104
        getFFmpeg(self)->setPreseek(PyInt_AsLong(value));
 
1105
        // success
 
1106
        return 0;
 
1107
}
 
1108
 
 
1109
// get deinterlace
 
1110
PyObject * VideoFFmpeg_getDeinterlace (PyImage * self, void * closure)
 
1111
{
 
1112
        if (getFFmpeg(self)->getDeinterlace())
 
1113
                Py_RETURN_TRUE;
 
1114
        else
 
1115
                Py_RETURN_FALSE;
 
1116
}
 
1117
 
 
1118
// set flip
 
1119
int VideoFFmpeg_setDeinterlace (PyImage * self, PyObject * value, void * closure)
 
1120
{
 
1121
        // check parameter, report failure
 
1122
        if (value == NULL || !PyBool_Check(value))
 
1123
        {
 
1124
                PyErr_SetString(PyExc_TypeError, "The value must be a bool");
 
1125
                return -1;
 
1126
        }
 
1127
        // set deinterlace
 
1128
        getFFmpeg(self)->setDeinterlace(value == Py_True);
 
1129
        // success
 
1130
        return 0;
 
1131
}
 
1132
 
 
1133
// methods structure
 
1134
static PyMethodDef videoMethods[] =
 
1135
{ // methods from VideoBase class
 
1136
        {"play", (PyCFunction)Video_play, METH_NOARGS, "Play (restart) video"},
 
1137
        {"pause", (PyCFunction)Video_pause, METH_NOARGS, "pause video"},
 
1138
        {"stop", (PyCFunction)Video_stop, METH_NOARGS, "stop video (play will replay it from start)"},
 
1139
        {"refresh", (PyCFunction)Video_refresh, METH_NOARGS, "Refresh video - get its status"},
 
1140
        {NULL}
 
1141
};
 
1142
// attributes structure
 
1143
static PyGetSetDef videoGetSets[] =
 
1144
{ // methods from VideoBase class
 
1145
        {(char*)"status", (getter)Video_getStatus, NULL, (char*)"video status", NULL},
 
1146
        {(char*)"range", (getter)Video_getRange, (setter)Video_setRange, (char*)"replay range", NULL},
 
1147
        {(char*)"repeat", (getter)Video_getRepeat, (setter)Video_setRepeat, (char*)"repeat count, -1 for infinite repeat", NULL},
 
1148
        {(char*)"framerate", (getter)Video_getFrameRate, (setter)Video_setFrameRate, (char*)"frame rate", NULL},
 
1149
        // attributes from ImageBase class
 
1150
        {(char*)"image", (getter)Image_getImage, NULL, (char*)"image data", NULL},
 
1151
        {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL},
 
1152
        {(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbour)", NULL},
 
1153
        {(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL},
 
1154
        {(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL},
 
1155
        {(char*)"preseek", (getter)VideoFFmpeg_getPreseek, (setter)VideoFFmpeg_setPreseek, (char*)"nb of frames of preseek", NULL},
 
1156
        {(char*)"deinterlace", (getter)VideoFFmpeg_getDeinterlace, (setter)VideoFFmpeg_setDeinterlace, (char*)"deinterlace image", NULL},
 
1157
        {NULL}
 
1158
};
 
1159
 
 
1160
// python type declaration
 
1161
PyTypeObject VideoFFmpegType =
 
1162
 
1163
#if (PY_VERSION_HEX >= 0x02060000)
 
1164
        PyVarObject_HEAD_INIT(NULL, 0)
 
1165
#else
 
1166
        /* python 2.5 and below */
 
1167
        PyObject_HEAD_INIT( NULL )  /* required py macro */
 
1168
        0,                         /*ob_size*/
 
1169
#endif
 
1170
        "VideoTexture.VideoFFmpeg",   /*tp_name*/
 
1171
        sizeof(PyImage),          /*tp_basicsize*/
 
1172
        0,                         /*tp_itemsize*/
 
1173
        (destructor)Image_dealloc, /*tp_dealloc*/
 
1174
        0,                         /*tp_print*/
 
1175
        0,                         /*tp_getattr*/
 
1176
        0,                         /*tp_setattr*/
 
1177
        0,                         /*tp_compare*/
 
1178
        0,                         /*tp_repr*/
 
1179
        0,                         /*tp_as_number*/
 
1180
        0,                         /*tp_as_sequence*/
 
1181
        0,                         /*tp_as_mapping*/
 
1182
        0,                         /*tp_hash */
 
1183
        0,                         /*tp_call*/
 
1184
        0,                         /*tp_str*/
 
1185
        0,                         /*tp_getattro*/
 
1186
        0,                         /*tp_setattro*/
 
1187
        0,                         /*tp_as_buffer*/
 
1188
        Py_TPFLAGS_DEFAULT,        /*tp_flags*/
 
1189
        "FFmpeg video source",       /* tp_doc */
 
1190
        0,                             /* tp_traverse */
 
1191
        0,                             /* tp_clear */
 
1192
        0,                             /* tp_richcompare */
 
1193
        0,                             /* tp_weaklistoffset */
 
1194
        0,                             /* tp_iter */
 
1195
        0,                             /* tp_iternext */
 
1196
        videoMethods,    /* tp_methods */
 
1197
        0,                   /* tp_members */
 
1198
        videoGetSets,          /* tp_getset */
 
1199
        0,                         /* tp_base */
 
1200
        0,                         /* tp_dict */
 
1201
        0,                         /* tp_descr_get */
 
1202
        0,                         /* tp_descr_set */
 
1203
        0,                         /* tp_dictoffset */
 
1204
        (initproc)VideoFFmpeg_init,     /* tp_init */
 
1205
        0,                         /* tp_alloc */
 
1206
        Image_allocNew,           /* tp_new */
 
1207
};
 
1208
 
 
1209
// object initialization
 
1210
static int ImageFFmpeg_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
 
1211
{
 
1212
        PyImage * self = reinterpret_cast<PyImage*>(pySelf);
 
1213
        // parameters - video source
 
1214
        // file name or format type for capture (only for Linux: video4linux or dv1394)
 
1215
        char * file = NULL;
 
1216
 
 
1217
        // get parameters
 
1218
        if (!PyArg_ParseTuple(args, "s:ImageFFmpeg", &file))
 
1219
                return -1; 
 
1220
 
 
1221
        try
 
1222
        {
 
1223
                // create video object
 
1224
                Video_init<VideoFFmpeg>(self);
 
1225
 
 
1226
                getVideoFFmpeg(self)->initParams(0, 0, 1.0, true);
 
1227
 
 
1228
                // open video source
 
1229
                Video_open(getVideo(self), file, -1);
 
1230
        }
 
1231
        catch (Exception & exp)
 
1232
        {
 
1233
                exp.report();
 
1234
                return -1;
 
1235
        }
 
1236
        // initialization succeded
 
1237
        return 0;
 
1238
}
 
1239
 
 
1240
PyObject * Image_reload (PyImage * self, PyObject *args)
 
1241
{
 
1242
        char * newname = NULL;
 
1243
        if (!PyArg_ParseTuple(args, "|s:reload", &newname))
 
1244
                return NULL;
 
1245
        if (self->m_image != NULL)
 
1246
        {
 
1247
                VideoFFmpeg* video = getFFmpeg(self);
 
1248
                // check type of object
 
1249
                if (!newname)
 
1250
                        newname = video->getImageName();
 
1251
                if (!newname) {
 
1252
                        // if not set, retport error
 
1253
                        PyErr_SetString(PyExc_RuntimeError, "No image file name given");
 
1254
                        return NULL;
 
1255
                }
 
1256
                // make sure the previous file is cleared
 
1257
                video->release();
 
1258
                // open the new file
 
1259
                video->openFile(newname);
 
1260
        }
 
1261
        Py_RETURN_NONE;
 
1262
}
 
1263
 
 
1264
// methods structure
 
1265
static PyMethodDef imageMethods[] =
 
1266
{ // methods from VideoBase class
 
1267
        {"refresh", (PyCFunction)Video_refresh, METH_NOARGS, "Refresh image, i.e. load it"},
 
1268
        {"reload", (PyCFunction)Image_reload, METH_VARARGS, "Reload image, i.e. reopen it"},
 
1269
        {NULL}
 
1270
};
 
1271
// attributes structure
 
1272
static PyGetSetDef imageGetSets[] =
 
1273
{ // methods from VideoBase class
 
1274
        {(char*)"status", (getter)Video_getStatus, NULL, (char*)"video status", NULL},
 
1275
        // attributes from ImageBase class
 
1276
        {(char*)"image", (getter)Image_getImage, NULL, (char*)"image data", NULL},
 
1277
        {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL},
 
1278
        {(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbour)", NULL},
 
1279
        {(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL},
 
1280
        {(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL},
 
1281
        {NULL}
 
1282
};
 
1283
 
 
1284
// python type declaration
 
1285
PyTypeObject ImageFFmpegType =
 
1286
 
1287
#if (PY_VERSION_HEX >= 0x02060000)
 
1288
        PyVarObject_HEAD_INIT(NULL, 0)
 
1289
#else
 
1290
        /* python 2.5 and below */
 
1291
        PyObject_HEAD_INIT( NULL )  /* required py macro */
 
1292
        0,                         /*ob_size*/
 
1293
#endif
 
1294
        "VideoTexture.ImageFFmpeg",   /*tp_name*/
 
1295
        sizeof(PyImage),          /*tp_basicsize*/
 
1296
        0,                         /*tp_itemsize*/
 
1297
        (destructor)Image_dealloc, /*tp_dealloc*/
 
1298
        0,                         /*tp_print*/
 
1299
        0,                         /*tp_getattr*/
 
1300
        0,                         /*tp_setattr*/
 
1301
        0,                         /*tp_compare*/
 
1302
        0,                         /*tp_repr*/
 
1303
        0,                         /*tp_as_number*/
 
1304
        0,                         /*tp_as_sequence*/
 
1305
        0,                         /*tp_as_mapping*/
 
1306
        0,                         /*tp_hash */
 
1307
        0,                         /*tp_call*/
 
1308
        0,                         /*tp_str*/
 
1309
        0,                         /*tp_getattro*/
 
1310
        0,                         /*tp_setattro*/
 
1311
        0,                         /*tp_as_buffer*/
 
1312
        Py_TPFLAGS_DEFAULT,        /*tp_flags*/
 
1313
        "FFmpeg image source",       /* tp_doc */
 
1314
        0,                             /* tp_traverse */
 
1315
        0,                             /* tp_clear */
 
1316
        0,                             /* tp_richcompare */
 
1317
        0,                             /* tp_weaklistoffset */
 
1318
        0,                             /* tp_iter */
 
1319
        0,                             /* tp_iternext */
 
1320
        imageMethods,    /* tp_methods */
 
1321
        0,                   /* tp_members */
 
1322
        imageGetSets,          /* tp_getset */
 
1323
        0,                         /* tp_base */
 
1324
        0,                         /* tp_dict */
 
1325
        0,                         /* tp_descr_get */
 
1326
        0,                         /* tp_descr_set */
 
1327
        0,                         /* tp_dictoffset */
 
1328
        (initproc)ImageFFmpeg_init,     /* tp_init */
 
1329
        0,                         /* tp_alloc */
 
1330
        Image_allocNew,           /* tp_new */
 
1331
};
 
1332
 
 
1333
#endif  //WITH_FFMPEG
 
1334
 
 
1335