1
/* $Id: VideoFFmpeg.cpp 20689 2009-06-06 21:54:12Z ben2610 $
2
-----------------------------------------------------------------------------
3
This source file is part of VideoTexture library
5
Copyright (c) 2007 The Zdeno Ash Miklas
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
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.
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
-----------------------------------------------------------------------------
25
// INT64_C fix for some linux machines (C99ism)
26
#define __STDC_CONSTANT_MACROS
30
#include "MEM_guardedalloc.h"
35
#include "Exception.h"
36
#include "VideoFFmpeg.h"
40
const double defFrameRate = 25.0;
41
// time scale constant
42
const long timeScale = 1000;
44
// macro for exception handling and logging
45
#define CATCH_EXCP catch (Exception & exp) \
46
{ exp.report(); m_status = SourceError; }
48
extern "C" void do_init_ffmpeg();
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)
63
// force flip because ffmpeg always return the image in the wrong orientation for texture
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;
76
VideoFFmpeg::~VideoFFmpeg ()
82
bool VideoFFmpeg::release()
88
avcodec_close(m_codecCtx);
93
av_close_input_file(m_formatCtx);
101
if (m_frameDeinterlaced)
103
MEM_freeN(m_frameDeinterlaced->data[0]);
104
av_free(m_frameDeinterlaced);
105
m_frameDeinterlaced = NULL;
109
MEM_freeN(m_frameRGB->data[0]);
115
sws_freeContext(m_imgConvertCtx);
116
m_imgConvertCtx = NULL;
119
m_status = SourceStopped;
124
AVFrame *VideoFFmpeg::allocFrameRGB()
127
frame = avcodec_alloc_frame();
128
if (m_format == RGBA32)
130
avpicture_fill((AVPicture*)frame,
131
(uint8_t*)MEM_callocN(avpicture_get_size(
133
m_codecCtx->width, m_codecCtx->height),
135
PIX_FMT_RGBA, m_codecCtx->width, m_codecCtx->height);
138
avpicture_fill((AVPicture*)frame,
139
(uint8_t*)MEM_callocN(avpicture_get_size(
141
m_codecCtx->width, m_codecCtx->height),
143
PIX_FMT_RGB24, m_codecCtx->width, m_codecCtx->height);
148
// set initial parameters
149
void VideoFFmpeg::initParams (short width, short height, float rate, bool image)
152
m_captHeight = height;
158
int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AVFormatParameters *formatParams)
160
AVFormatContext *formatCtx;
163
AVCodecContext *codecCtx;
165
if(av_open_input_file(&formatCtx, filename, inputFormat, 0, formatParams)!=0)
168
if(av_find_stream_info(formatCtx)<0)
170
av_close_input_file(formatCtx);
174
/* Find the first video stream */
176
for(i=0; i<formatCtx->nb_streams; i++)
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))
189
av_close_input_file(formatCtx);
193
codecCtx = get_codec_from_stream(formatCtx->streams[videoStream]);
195
/* Find the decoder for the video stream */
196
codec=avcodec_find_decoder(codecCtx->codec_id);
199
av_close_input_file(formatCtx);
202
codecCtx->workaround_bugs = 1;
203
if(avcodec_open(codecCtx, codec)<0)
205
av_close_input_file(formatCtx);
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;
214
m_baseFrameRate = av_q2d(formatCtx->streams[videoStream]->r_frame_rate);
216
if (m_baseFrameRate <= 0.0)
217
m_baseFrameRate = defFrameRate;
220
m_codecCtx = codecCtx;
221
m_formatCtx = formatCtx;
222
m_videoStream = videoStream;
223
m_frame = avcodec_alloc_frame();
224
m_frameDeinterlaced = avcodec_alloc_frame();
226
// allocate buffer if deinterlacing is required
227
avpicture_fill((AVPicture*)m_frameDeinterlaced,
228
(uint8_t*)MEM_callocN(avpicture_get_size(
230
m_codecCtx->width, m_codecCtx->height),
231
"ffmpeg deinterlace"),
232
m_codecCtx->pix_fmt, m_codecCtx->width, m_codecCtx->height);
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)
240
// allocate buffer to store final decoded frame
242
// allocate sws context
243
m_imgConvertCtx = sws_getContext(
254
// allocate buffer to store final decoded frame
256
// allocate sws context
257
m_imgConvertCtx = sws_getContext(
267
m_frameRGB = allocFrameRGB();
269
if (!m_imgConvertCtx) {
270
avcodec_close(m_codecCtx);
272
av_close_input_file(m_formatCtx);
276
MEM_freeN(m_frameDeinterlaced->data[0]);
277
av_free(m_frameDeinterlaced);
278
m_frameDeinterlaced = NULL;
279
MEM_freeN(m_frameRGB->data[0]);
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.
299
void *VideoFFmpeg::cacheThread(void *data)
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;
308
while (!video->m_stopThread)
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
315
&& (cachePacket = (CachePacket *)video->m_packetCacheFree.first) != NULL
316
&& frameFinished < 25)
318
// free packet => packet cache is not full yet, just read more
319
if (av_read_frame(video->m_formatCtx, &cachePacket->packet)>=0)
321
if (cachePacket->packet.stream_index == video->m_videoStream)
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);
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);
337
// this mark the end of the file
339
// if we cannot read a packet, no need to continue
343
// frame cache is also used by main thread, lock
344
if (currentFrame == NULL)
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);
352
if (currentFrame != NULL)
354
// this frame is out of free and busy queue, we can manipulate it without locking
356
while (!frameFinished && (cachePacket = (CachePacket *)video->m_packetCacheBase.first) != NULL)
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);
366
AVFrame * input = video->m_frame;
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)
372
if (video->m_deinterlace)
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)
381
input = video->m_frameDeinterlaced;
385
sws_scale(video->m_imgConvertCtx,
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);
400
av_free_packet(&cachePacket->packet);
401
BLI_addtail(&video->m_packetCacheFree, cachePacket);
403
if (currentFrame && endOfFile)
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);
411
// no need to stay any longer in this thread
415
// small sleep to avoid unnecessary looping
418
// before quitting, put back the current frame to queue to allow freeing
421
pthread_mutex_lock(&video->m_cacheMutex);
422
BLI_addtail(&video->m_frameCacheFree, currentFrame);
423
pthread_mutex_unlock(&video->m_cacheMutex);
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()
433
if (!m_cacheStarted && m_isThreaded)
435
m_stopThread = false;
436
for (int i=0; i<CACHE_FRAME_SIZE; i++)
438
CacheFrame *frame = new CacheFrame();
439
frame->frame = allocFrameRGB();
440
BLI_addtail(&m_frameCacheFree, frame);
442
for (int i=0; i<CACHE_PACKET_SIZE; i++)
444
CachePacket *packet = new CachePacket();
445
BLI_addtail(&m_packetCacheFree, packet);
447
BLI_init_threads(&m_thread, cacheThread, 1);
448
BLI_insert_thread(&m_thread, this);
449
m_cacheStarted = true;
451
return m_cacheStarted;
454
void VideoFFmpeg::stopCache()
459
BLI_end_threads(&m_thread);
460
// now delete the cache
463
while ((frame = (CacheFrame *)m_frameCacheBase.first) != NULL)
465
BLI_remlink(&m_frameCacheBase, frame);
466
MEM_freeN(frame->frame->data[0]);
467
av_free(frame->frame);
470
while ((frame = (CacheFrame *)m_frameCacheFree.first) != NULL)
472
BLI_remlink(&m_frameCacheFree, frame);
473
MEM_freeN(frame->frame->data[0]);
474
av_free(frame->frame);
477
while((packet = (CachePacket *)m_packetCacheBase.first) != NULL)
479
BLI_remlink(&m_packetCacheBase, packet);
480
av_free_packet(&packet->packet);
483
while((packet = (CachePacket *)m_packetCacheFree.first) != NULL)
485
BLI_remlink(&m_packetCacheFree, packet);
488
m_cacheStarted = false;
492
void VideoFFmpeg::releaseFrame(AVFrame* frame)
494
if (frame == m_frameRGB)
496
// this is not a frame from the cache, ignore
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);
509
void VideoFFmpeg::openFile (char * filename)
513
if (openStream(filename, NULL, NULL) != 0)
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
523
// get video time range
525
m_range[1] = (double)m_formatCtx->duration / AV_TIME_BASE;
528
VideoBase::openFile(filename);
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)
538
m_formatCtx->pb.is_streamed
542
// the file is in fact a streaming source, prevent seeking
544
// for streaming it is important to do non blocking read
545
m_formatCtx->flags |= AVFMT_FLAG_NONBLOCK;
550
// the file is to be treated as an image, i.e. load the first frame only
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;
559
// check if we should do multi-threading?
560
if (!m_isImage && BLI_system_thread_count() > 1)
562
// never thread image: there are no frame to read ahead
563
// no need to thread if the system has a single core
569
// open video capture device
570
void VideoFFmpeg::openCam (char * file, short camIdx)
572
// open camera source
573
AVInputFormat *inputFormat;
574
AVFormatParameters formatParams;
575
AVRational frameRate;
576
char *p, filename[28], rateStr[20];
580
memset(&formatParams, 0, sizeof(formatParams));
582
// video capture on windows only through Video For Windows driver
583
inputFormat = av_find_input_format("vfwcap");
585
// Video For Windows not supported??
587
sprintf(filename, "%d", camIdx);
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
603
if (file && strstr(file, "1394") != NULL)
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);
610
inputFormat = av_find_input_format("video4linux");
611
sprintf(filename, "/dev/video%d", camIdx);
614
// these format should be supported, check ffmpeg compilation
616
if (file && strncmp(file, "/dev", 4) == 0)
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)
624
if (file && (p = strchr(file, ':')) != NULL)
625
formatParams.standard = p+1;
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;
639
if (openStream(filename, inputFormat, &formatParams) != 0)
642
// for video capture it is important to do non blocking read
643
m_formatCtx->flags |= AVFMT_FLAG_NONBLOCK;
645
VideoBase::openCam(file, camIdx);
646
// check if we should do multi-threading?
647
if (BLI_system_thread_count() > 1)
649
// no need to thread if the system has a single core
655
bool VideoFFmpeg::play (void)
659
// if object is able to play
660
if (VideoBase::play())
662
// set video position
674
bool VideoFFmpeg::pause (void)
678
if (VideoBase::pause())
688
bool VideoFFmpeg::stop (void)
693
// force restart when play
703
void VideoFFmpeg::setRange (double start, double stop)
710
VideoBase::setRange(start, stop);
711
// set range for video
719
void VideoFFmpeg::setFrameRate (float rate)
721
VideoBase::setFrameRate(rate);
726
void VideoFFmpeg::calcImage (unsigned int texId)
732
// load frame from video
733
void VideoFFmpeg::loadFrame (void)
735
if (m_status == SourcePlaying)
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])
745
// in any case, this resets the cache
747
// if repeats are set, decrease them
750
// if video has to be replayed
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;
757
// if video has to be stopped, stop it
760
m_status = SourceStopped;
765
long actFrame = (m_isImage) ? m_lastFrame+1 : long(actTime * actFrameRate());
766
// if actual frame differs from last frame
767
if (actFrame != m_lastFrame)
771
if((frame = grabFrame(actFrame)) != NULL)
773
if (!m_isFile && !m_cacheStarted)
775
// streaming without cache: detect synchronization problem
776
double execTime = PIL_check_seconds_timer() - startTime;
777
if (execTime > 0.005)
779
// exec time is too long, it means that the function was blocking
780
// resynchronize the stream from this time
781
m_startTime += execTime;
785
m_lastFrame = actFrame;
786
// init image, if needed
787
init(short(m_codecCtx->width), short(m_codecCtx->height));
789
process((BYTE*)(frame->data[0]));
790
// finished with the frame, release it so that cache can reuse it
792
// in case it is an image, automatically stop reading it
795
m_status = SourceStopped;
796
// close the file as we don't need it anymore
799
} else if (!m_isFile)
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
811
// set actual position
812
void VideoFFmpeg::setPositions (void)
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();
821
m_startTime -= m_range[0];
822
// start from begining, stop cache just in case
827
// position pointer in file, position in second
828
AVFrame *VideoFFmpeg::grabFrame(long position)
833
bool frameLoaded = false;
834
long long targetTs = 0;
839
// when cache is active, we must not read the file directly
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
847
// no frame in cache, in case of file it is an abnormal situation
850
// go back to no threaded reading
856
if (frame->framePosition == -1)
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
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)
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);
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)
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
884
&& position - (m_curPosition + 1) < m_preseek)
886
while(av_read_frame(m_formatCtx, &packet)>=0)
888
if (packet.stream_index == m_videoStream)
890
avcodec_decode_video(
892
m_frame, &frameFinished,
893
packet.data, packet.size);
897
av_free_packet(&packet);
898
if (position == m_curPosition+1)
902
// if the position is not in preseek, do a direct jump
903
if (position != m_curPosition + 1)
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;
913
if (startTs != AV_NOPTS_VALUE)
916
if (position <= m_curPosition || !m_eof)
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
923
if (position <= m_preseek)
925
// we can safely go the begining of the file
926
if (av_seek_frame(m_formatCtx, m_videoStream, 0, AVSEEK_FLAG_BYTE) >= 0)
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);
936
// current position is now lost, guess a value.
937
if (av_seek_frame(m_formatCtx, m_videoStream, pos, AVSEEK_FLAG_BACKWARD) >= 0)
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;
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)
951
avcodec_flush_buffers(m_codecCtx);
953
} else if (m_isThreaded)
955
// cache is not started but threading is possible
956
// better not read the stream => make take some time, better start caching
959
// Abnormal!!! could not start cache, fall back on direct read
960
m_isThreaded = false;
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)
967
if(packet.stream_index == m_videoStream)
969
avcodec_decode_video(m_codecCtx,
970
m_frame, &frameFinished,
971
packet.data, packet.size);
973
if (frameFinished && !posFound)
975
if (packet.dts >= targetTs)
979
if(frameFinished && posFound == 1)
981
AVFrame * input = m_frame;
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)
988
av_free_packet(&packet);
994
if (avpicture_deinterlace(
995
(AVPicture*) m_frameDeinterlaced,
996
(const AVPicture*) m_frame,
999
m_codecCtx->height) >= 0)
1001
input = m_frameDeinterlaced;
1005
sws_scale(m_imgConvertCtx,
1011
m_frameRGB->linesize);
1012
av_free_packet(&packet);
1017
av_free_packet(&packet);
1019
m_eof = m_isFile && !frameLoaded;
1022
m_curPosition = position;
1025
// normal case for file: first locate, then start cache
1028
// Abnormal!! could not start cache, return to non-cache mode
1029
m_isThreaded = false;
1041
// cast Image pointer to VideoFFmpeg
1042
inline VideoFFmpeg * getVideoFFmpeg (PyImage * self)
1043
{ return static_cast<VideoFFmpeg*>(self->m_image); }
1046
// object initialization
1047
static int VideoFFmpeg_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
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)
1053
// capture device number
1055
// capture width, only if capt is >= 0
1057
// capture height, only if capt is >= 0
1059
// capture rate, only if capt is >= 0
1062
static char *kwlist[] = {"file", "capture", "rate", "width", "height", NULL};
1065
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|hfhh", kwlist, &file, &capt,
1066
&rate, &width, &height))
1071
// create video object
1072
Video_init<VideoFFmpeg>(self);
1075
getVideoFFmpeg(self)->initParams(width, height, rate);
1077
// open video source
1078
Video_open(getVideo(self), file, capt);
1080
catch (Exception & exp)
1085
// initialization succeded
1089
PyObject * VideoFFmpeg_getPreseek (PyImage *self, void * closure)
1091
return Py_BuildValue("h", getFFmpeg(self)->getPreseek());
1095
int VideoFFmpeg_setPreseek (PyImage * self, PyObject * value, void * closure)
1097
// check validity of parameter
1098
if (value == NULL || !PyInt_Check(value))
1100
PyErr_SetString(PyExc_TypeError, "The value must be an integer");
1104
getFFmpeg(self)->setPreseek(PyInt_AsLong(value));
1110
PyObject * VideoFFmpeg_getDeinterlace (PyImage * self, void * closure)
1112
if (getFFmpeg(self)->getDeinterlace())
1119
int VideoFFmpeg_setDeinterlace (PyImage * self, PyObject * value, void * closure)
1121
// check parameter, report failure
1122
if (value == NULL || !PyBool_Check(value))
1124
PyErr_SetString(PyExc_TypeError, "The value must be a bool");
1128
getFFmpeg(self)->setDeinterlace(value == Py_True);
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"},
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},
1160
// python type declaration
1161
PyTypeObject VideoFFmpegType =
1163
#if (PY_VERSION_HEX >= 0x02060000)
1164
PyVarObject_HEAD_INIT(NULL, 0)
1166
/* python 2.5 and below */
1167
PyObject_HEAD_INIT( NULL ) /* required py macro */
1170
"VideoTexture.VideoFFmpeg", /*tp_name*/
1171
sizeof(PyImage), /*tp_basicsize*/
1173
(destructor)Image_dealloc, /*tp_dealloc*/
1180
0, /*tp_as_sequence*/
1181
0, /*tp_as_mapping*/
1188
Py_TPFLAGS_DEFAULT, /*tp_flags*/
1189
"FFmpeg video source", /* tp_doc */
1190
0, /* tp_traverse */
1192
0, /* tp_richcompare */
1193
0, /* tp_weaklistoffset */
1195
0, /* tp_iternext */
1196
videoMethods, /* tp_methods */
1198
videoGetSets, /* tp_getset */
1201
0, /* tp_descr_get */
1202
0, /* tp_descr_set */
1203
0, /* tp_dictoffset */
1204
(initproc)VideoFFmpeg_init, /* tp_init */
1206
Image_allocNew, /* tp_new */
1209
// object initialization
1210
static int ImageFFmpeg_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
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)
1218
if (!PyArg_ParseTuple(args, "s:ImageFFmpeg", &file))
1223
// create video object
1224
Video_init<VideoFFmpeg>(self);
1226
getVideoFFmpeg(self)->initParams(0, 0, 1.0, true);
1228
// open video source
1229
Video_open(getVideo(self), file, -1);
1231
catch (Exception & exp)
1236
// initialization succeded
1240
PyObject * Image_reload (PyImage * self, PyObject *args)
1242
char * newname = NULL;
1243
if (!PyArg_ParseTuple(args, "|s:reload", &newname))
1245
if (self->m_image != NULL)
1247
VideoFFmpeg* video = getFFmpeg(self);
1248
// check type of object
1250
newname = video->getImageName();
1252
// if not set, retport error
1253
PyErr_SetString(PyExc_RuntimeError, "No image file name given");
1256
// make sure the previous file is cleared
1258
// open the new file
1259
video->openFile(newname);
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"},
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},
1284
// python type declaration
1285
PyTypeObject ImageFFmpegType =
1287
#if (PY_VERSION_HEX >= 0x02060000)
1288
PyVarObject_HEAD_INIT(NULL, 0)
1290
/* python 2.5 and below */
1291
PyObject_HEAD_INIT( NULL ) /* required py macro */
1294
"VideoTexture.ImageFFmpeg", /*tp_name*/
1295
sizeof(PyImage), /*tp_basicsize*/
1297
(destructor)Image_dealloc, /*tp_dealloc*/
1304
0, /*tp_as_sequence*/
1305
0, /*tp_as_mapping*/
1312
Py_TPFLAGS_DEFAULT, /*tp_flags*/
1313
"FFmpeg image source", /* tp_doc */
1314
0, /* tp_traverse */
1316
0, /* tp_richcompare */
1317
0, /* tp_weaklistoffset */
1319
0, /* tp_iternext */
1320
imageMethods, /* tp_methods */
1322
imageGetSets, /* tp_getset */
1325
0, /* tp_descr_get */
1326
0, /* tp_descr_set */
1327
0, /* tp_dictoffset */
1328
(initproc)ImageFFmpeg_init, /* tp_init */
1330
Image_allocNew, /* tp_new */
1333
#endif //WITH_FFMPEG