2
pygame - Python Game Library
3
Copyright (C) 2000-2001 Pete Shinners
5
This library is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Library General Public
7
License as published by the Free Software Foundation; either
8
version 2 of the License, or (at your option) any later version.
10
This library is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
Library General Public License for more details.
15
You should have received a copy of the GNU Library General Public
16
License along with this library; if not, write to the Free
17
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
This code based on the sample "ffplay" included with ffmpeg.
23
The ffmpeg library is released as LGPL software.
30
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
34
static int Global_abort_all = 0;
35
static int Global_num_active = 0;
38
static void print_error(const char *filename, int err)
41
case AVERROR_NUMEXPECTED:
42
fprintf(stderr, "%s: Incorrect image filename syntax.\n"
43
"Use '%%d' to specify the image number:\n"
44
" for img1.jpg, img2.jpg, ..., use 'img%%d.jpg';\n"
45
" for img001.jpg, img002.jpg, ..., use 'img%%03d.jpg'.\n",
48
case AVERROR_INVALIDDATA:
49
fprintf(stderr, "%s: Error while parsing header\n", filename);
52
fprintf(stderr, "%s: Unknown format\n", filename);
55
fprintf(stderr, "%s: Error while opening file (%d)\n", filename, err);
63
/* packet queue handling */
64
static void packet_queue_init(PacketQueue *q)
66
memset(q, 0, sizeof(PacketQueue));
67
q->mutex = SDL_CreateMutex();
68
q->cond = SDL_CreateCond();
71
static void packet_queue_end(PacketQueue *q)
73
AVPacketList *pkt, *pkt1;
75
for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
77
av_free_packet(&pkt->pkt);
79
SDL_DestroyMutex(q->mutex);
80
SDL_DestroyCond(q->cond);
83
static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
87
pkt1 = av_malloc(sizeof(AVPacketList));
93
SDL_LockMutex(q->mutex);
99
q->last_pkt->next = pkt1;
102
q->size += pkt1->pkt.size;
103
/* XXX: should duplicate packet data in DV case */
104
SDL_CondSignal(q->cond);
106
SDL_UnlockMutex(q->mutex);
110
static void packet_queue_abort(PacketQueue *q)
112
SDL_LockMutex(q->mutex);
114
q->abort_request = 1;
116
SDL_CondSignal(q->cond);
118
SDL_UnlockMutex(q->mutex);
121
/* return < 0 if aborted, 0 if no packet and > 0 if packet. */
122
static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
127
SDL_LockMutex(q->mutex);
130
if (q->abort_request || Global_abort_all) {
137
q->first_pkt = pkt1->next;
141
q->size -= pkt1->pkt.size;
150
SDL_CondWait(q->cond, q->mutex);
153
SDL_UnlockMutex(q->mutex);
161
static void video_display(FFMovie *movie)
163
/*DECODE THREAD - from video_refresh_timer*/
165
SDL_LockMutex(movie->dest_mutex);
166
if (movie->dest_overlay) {
167
SDL_DisplayYUVOverlay(movie->dest_overlay, &movie->dest_rect);
169
SDL_UnlockMutex(movie->dest_mutex);
173
/* get the current audio clock value */
174
static double get_audio_clock(FFMovie *movie)
178
int hw_buf_size, bytes_per_sec;
179
pts = movie->audio_clock;
180
hw_buf_size = movie->audio_hw_buf_size - movie->audio_buf_index;
182
if (movie->audio_st) {
183
bytes_per_sec = movie->audio_st->codec.sample_rate *
184
2 * movie->audio_st->codec.channels;
187
pts -= (double)hw_buf_size / bytes_per_sec;
192
static double get_master_clock(FFMovie *movie) {
193
Uint32 ticks = SDL_GetTicks();
194
return (ticks / 1000.0) - movie->time_offset;
199
/* called to display each frame */
200
static void video_refresh_timer(FFMovie* movie)
202
/*moving to DECODE THREAD, from queue_frame*/
203
double actual_delay, delay, sync_threshold, ref_clock, diff;
206
if (movie->video_st) { /*shouldn't ever even get this far if no video_st*/
208
/* update current video pts */
209
movie->video_current_pts = movie->video_clock;
211
/* compute nominal delay */
212
delay = movie->video_clock - movie->frame_last_pts;
213
if (delay <= 0 || delay >= 1.0) {
214
/* if incorrect delay, use previous one */
215
delay = movie->frame_last_delay;
217
movie->frame_last_delay = delay;
218
movie->frame_last_pts = movie->video_clock;
220
/* we try to correct big delays by duplicating or deleting a frame */
221
ref_clock = get_master_clock(movie);
222
diff = movie->video_clock - ref_clock;
224
//printf("get_master_clock = %f\n", (float)(ref_clock/1000000.0));
225
/* skip or repeat frame. We take into account the delay to compute
226
the threshold. I still don't know if it is the best guess */
227
sync_threshold = AV_SYNC_THRESHOLD;
228
if (delay > sync_threshold)
229
sync_threshold = delay;
230
if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
231
if (diff <= -sync_threshold) {
234
} else if (diff >= sync_threshold) {
239
movie->frame_timer += delay;
240
actual_delay = movie->frame_timer - get_master_clock(movie);
241
//printf("DELAY: delay=%f, frame_timer=%f, video_clock=%f\n",
242
// (float)delay, (float)movie->frame_timer, (float)movie->video_clock);
243
if (actual_delay > 0.010) {
244
movie->dest_showtime = movie->frame_timer;
247
movie->dest_showtime = 0;
248
/*movie->dest_showtime = get_master_clock(movie); this shows every frame*/
255
static int queue_picture(FFMovie *movie, AVFrame *src_frame)
260
SDL_LockMutex(movie->dest_mutex);
262
/* if the frame movie not skipped, then display it */
264
if (movie->dest_overlay) {
265
/* get a pointer on the bitmap */
266
SDL_LockYUVOverlay(movie->dest_overlay);
268
pict.data[0] = movie->dest_overlay->pixels[0];
269
pict.data[1] = movie->dest_overlay->pixels[2];
270
pict.data[2] = movie->dest_overlay->pixels[1];
271
pict.linesize[0] = movie->dest_overlay->pitches[0];
272
pict.linesize[1] = movie->dest_overlay->pitches[2];
273
pict.linesize[2] = movie->dest_overlay->pitches[1];
276
first fields of AVFrame match AVPicture, so it appears safe to
277
cast here (at least of ffmpeg-0.4.8, this is how ffplay does it)
278
AVPicture is just a container for 4 pixel pointers and 4 strides
280
img_convert(&pict, PIX_FMT_YUV420P,
281
(AVPicture *)src_frame, movie->video_st->codec.pix_fmt,
282
movie->video_st->codec.width, movie->video_st->codec.height);
284
SDL_UnlockYUVOverlay(movie->dest_overlay);
286
video_refresh_timer(movie);
288
SDL_UnlockMutex(movie->dest_mutex);
294
static void update_video_clock(FFMovie *movie, AVFrame* frame, double pts) {
295
/* if B frames are present, and if the current picture is a I
296
or P frame, we use the last pts */
297
if (movie->video_st->codec.has_b_frames &&
298
frame->pict_type != FF_B_TYPE) {
300
double last_P_pts = movie->video_last_P_pts;
301
movie->video_last_P_pts = pts;
305
/* update video clock with pts, if present */
307
movie->video_clock = pts;
309
movie->video_clock += movie->frame_delay;
310
/* for MPEG2, the frame can be repeated, update accordingly */
311
if (frame->repeat_pict) {
312
movie->video_clock += frame->repeat_pict *
313
(movie->frame_delay * 0.5);
319
static int video_read_packet(FFMovie *movie, AVPacket *pkt)
323
int len, len1, got_picture;
328
if (movie->video_st->codec.codec_id == CODEC_ID_RAWVIDEO) {
329
avpicture_fill((AVPicture *)&frame, ptr,
330
movie->video_st->codec.pix_fmt,
331
movie->video_st->codec.width,
332
movie->video_st->codec.height);
333
if (pkt->pts != AV_NOPTS_VALUE)
334
pts = (double)pkt->pts * movie->context->pts_num / movie->context->pts_den;
337
frame.pict_type = FF_I_TYPE;
338
update_video_clock(movie, &frame, pts);
339
movie->frame_count++; /*this should probably represent displayed frames, not decoded*/
340
if (queue_picture(movie, &frame) < 0)
345
if (movie->vidpkt_start) {
346
movie->vidpkt_start = 0;
347
movie->vidpkt_timestamp = pkt->pts;
349
len1 = avcodec_decode_video(&movie->video_st->codec,
350
&frame, &got_picture, ptr, len);
354
movie->frame_count++; /*this should probably represent displayed frames, not decoded*/
355
if (movie->vidpkt_timestamp != AV_NOPTS_VALUE)
356
pts = (double)movie->vidpkt_timestamp * movie->context->pts_num / movie->context->pts_den;
359
update_video_clock(movie, &frame, pts);
360
if (queue_picture(movie, &frame) < 0)
362
movie->vidpkt_start = 1;
375
/* return the new audio buffer size (samples can be added or deleted
376
to get better sync if video or external master clock) */
377
static int synchronize_audio(FFMovie *movie, short *samples,
378
int samples_size1, double pts)
384
double diff, avg_diff;
385
int wanted_size, min_size, max_size, nb_samples;
388
n = 2 * movie->audio_st->codec.channels;
389
samples_size = samples_size1;
391
/* try to remove or add samples to correct the clock */
392
ref_clock = get_master_clock(movie);
393
diff = get_audio_clock(movie) - ref_clock;
395
if (diff < AV_NOSYNC_THRESHOLD) {
396
movie->audio_diff_cum = diff + movie->audio_diff_avg_coef * movie->audio_diff_cum;
397
if (movie->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
398
/* not enough measures to have a correct estimate */
399
movie->audio_diff_avg_count++;
401
/* estimate the A-V difference */
402
avg_diff = movie->audio_diff_cum * (1.0 - movie->audio_diff_avg_coef);
404
if (fabs(avg_diff) >= movie->audio_diff_threshold) {
405
wanted_size = samples_size + ((int)(diff * movie->audio_st->codec.sample_rate) * n);
406
nb_samples = samples_size / n;
408
min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
409
max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
410
if (wanted_size < min_size)
411
wanted_size = min_size;
412
else if (wanted_size > max_size)
413
wanted_size = max_size;
415
/* add or remove samples to correction the synchro */
416
if (wanted_size < samples_size) {
418
samples_size = wanted_size;
419
} else if (wanted_size > samples_size) {
420
uint8_t *samples_end, *q;
424
nb = (samples_size - wanted_size);
425
samples_end = (uint8_t *)samples + samples_size - n;
428
memcpy(q, samples_end, n);
432
samples_size = wanted_size;
437
/* too big difference : may be initial PTS errors, so
439
movie->audio_diff_avg_count = 0;
440
movie->audio_diff_cum = 0;
446
/* decode one audio frame and returns its uncompressed size */
447
static int audio_decode_frame(FFMovie *movie, uint8_t *audio_buf, double *pts_ptr)
450
AVPacket *pkt = &movie->audio_pkt;
455
if (movie->paused || movie->audioq.abort_request || Global_abort_all) {
458
while (movie->audio_pkt_size > 0) {
459
len1 = avcodec_decode_audio(&movie->audio_st->codec,
460
(int16_t *)audio_buf, &data_size,
461
movie->audio_pkt_data, movie->audio_pkt_size);
464
movie->audio_pkt_data += len1;
465
movie->audio_pkt_size -= len1;
468
if (movie->audio_pkt_ipts != AV_NOPTS_VALUE)
469
pts = (double)movie->audio_pkt_ipts * movie->context->pts_num / movie->context->pts_den;
470
/* if no pts, then compute it */
472
movie->audio_clock = pts;
475
n = 2 * movie->audio_st->codec.channels;
476
movie->audio_clock += (double)data_size / (double)(n * movie->audio_st->codec.sample_rate);
478
*pts_ptr = movie->audio_clock;
479
movie->audio_pkt_ipts = AV_NOPTS_VALUE;
480
/* we got samples : we can exit now */
485
/* free previous packet if any */
489
/* read next packet */
490
if (packet_queue_get(&movie->audioq, pkt, 1) < 0)
492
movie->audio_pkt_data = pkt->data;
493
movie->audio_pkt_size = pkt->size;
494
movie->audio_pkt_ipts = pkt->pts;
499
/* prepare a new audio buffer */
500
void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
503
FFMovie *movie = opaque;
504
int audio_size, len1;
508
if (movie->audio_buf_index >= movie->audio_buf_size) {
509
audio_size = audio_decode_frame(movie, movie->audio_buf, &pts);
510
if (audio_size < 0) {
511
/* if error, just output silence */
512
movie->audio_buf_size = 1024;
513
memset(movie->audio_buf, 0, movie->audio_buf_size);
515
audio_size = synchronize_audio(movie, (int16_t*)movie->audio_buf, audio_size, pts);
516
movie->audio_buf_size = audio_size;
518
movie->audio_buf_index = 0;
520
len1 = movie->audio_buf_size - movie->audio_buf_index;
523
memcpy(stream, (uint8_t *)movie->audio_buf + movie->audio_buf_index, len1);
526
movie->audio_buf_index += len1;
532
static void ffmovie_cleanup(FFMovie *movie) {
536
if(movie->audio_st) {
537
packet_queue_abort(&movie->audioq);
539
packet_queue_end(&movie->audioq);
540
avcodec_close(&movie->audio_st->codec);
541
movie->audio_st = NULL;
544
if(movie->video_st) {
545
avcodec_close(&movie->video_st->codec);
546
movie->video_st = NULL;
549
if (movie->context) {
550
av_close_input_file(movie->context);
551
movie->context = NULL;
554
if(movie->dest_mutex) {
555
SDL_DestroyMutex(movie->dest_mutex);
556
movie->dest_mutex = NULL;
559
if (movie->dest_overlay) {
560
SDL_FreeYUVOverlay(movie->dest_overlay);
561
movie->dest_overlay = NULL;
568
/* this thread gets the stream from the disk or the network */
569
static int decode_thread(void *arg)
572
FFMovie *movie = arg;
574
AVPacket pkt1, *pkt = &pkt1;
576
while(!movie->abort_request && !Global_abort_all) {
577
/* read if the queues have room */
578
if (movie->audioq.size < MAX_AUDIOQ_SIZE &&
579
!movie->dest_showtime) {
581
if (av_read_packet(movie->context, pkt) < 0) {
584
if (movie->audio_st &&
585
pkt->stream_index == movie->audio_st->index) {
586
packet_queue_put(&movie->audioq, pkt);
587
} else if (movie->video_st &&
588
pkt->stream_index == movie->video_st->index) {
589
status = video_read_packet(movie, pkt);
599
if(movie->dest_showtime) {
600
double now = get_master_clock(movie);
601
if(now >= movie->dest_showtime) {
602
video_display(movie);
603
movie->dest_showtime = 0;
605
// printf("showtime not ready, waiting... (%.2f,%.2f)\n",
606
// (float)now, (float)movie->dest_showtime);
613
double endpause, startpause = SDL_GetTicks() / 1000.0;
614
while(movie->paused && !movie->abort_request && !Global_abort_all) {
617
endpause = SDL_GetTicks() / 1000.0;
618
movie->dest_showtime = 0;
619
movie->time_offset += endpause - startpause;
623
ffmovie_cleanup(movie);
628
static int audiostream_init(FFMovie *movie, AVStream *stream)
632
SDL_AudioSpec wanted_spec, spec;
634
codec = avcodec_find_decoder(stream->codec.codec_id);
635
if (!codec || avcodec_open(&stream->codec, codec) < 0) {
639
/* init sdl audio output */
640
wanted_spec.freq = stream->codec.sample_rate;
641
wanted_spec.format = AUDIO_S16SYS;
642
wanted_spec.channels = stream->codec.channels;
643
if(wanted_spec.channels > 2)
644
wanted_spec.channels = 2;
645
wanted_spec.silence = 0;
646
wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
647
wanted_spec.callback = sdl_audio_callback;
648
wanted_spec.userdata = movie;
649
if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
650
fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
654
movie->audio_st = stream;
655
movie->audio_hw_buf_size = spec.size;
656
movie->audio_buf_size = 0;
657
movie->audio_buf_index = 0;
658
movie->audio_pkt_size = 0;
660
/* init averaging filter */
661
movie->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
662
movie->audio_diff_avg_count = 0;
663
/* since we do not have a precise anough audio fifo fullness,
664
we correct audio sync only if larger than this threshold */
665
movie->audio_diff_threshold = 2.0 *
666
SDL_AUDIO_BUFFER_SIZE / stream->codec.sample_rate;
667
/* should this be spec.freq instead of codec.sample_rate ?? */
669
memset(&movie->audio_pkt, 0, sizeof(movie->audio_pkt));
670
packet_queue_init(&movie->audioq);
677
static int videostream_init(FFMovie *movie, AVStream *stream)
682
codec = avcodec_find_decoder(stream->codec.codec_id);
683
if (!codec || avcodec_open(&stream->codec, codec) < 0)
686
movie->video_st = stream;
687
movie->frame_last_delay = 40e-3;
688
movie->frame_timer = SDL_GetTicks() / 1000.0;
690
movie->frame_delay = (double)movie->video_st->codec.frame_rate_base /
691
(double)movie->video_st->codec.frame_rate;
693
movie->vidpkt_start = 1;
695
movie->dest_mutex = SDL_CreateMutex();
702
static int ffmovie_initialized = 0;
705
FFMovie *ffmovie_open(const char *filename)
710
AVFormatParameters params = {0};
712
if(!ffmovie_initialized) {
713
ffmovie_initialized = 1;
717
movie = av_mallocz(sizeof(FFMovie));
721
err = av_open_input_file(&movie->context, filename, NULL, 0, ¶ms);
723
print_error(filename, err);
727
err = av_find_stream_info(movie->context);
730
fprintf(stderr, "%s: could not find codec parameters\n", filename);
734
/*find and open streams*/
735
for(i = 0; i < movie->context->nb_streams; i++) {
736
AVStream *stream = movie->context->streams[i];
737
switch(stream->codec.codec_type) {
738
case CODEC_TYPE_AUDIO:
739
if (!movie->audio_st && !movie->audio_disable)
740
audiostream_init(movie, stream);
742
case CODEC_TYPE_VIDEO:
743
if (!movie->video_st)
744
videostream_init(movie, stream);
750
if (!movie->video_st && !movie->audio_st) {
751
fprintf(stderr, "%s: could not open codecs\n", filename);
752
ffmovie_cleanup(movie);
756
movie->frame_count = 0;
757
movie->time_offset = 0.0;
759
movie->sourcename = strdup(filename);
762
movie->decode_thread = SDL_CreateThread(decode_thread, movie);
763
if (!movie->decode_thread) {
764
ffmovie_cleanup(movie);
771
void ffmovie_close(FFMovie *movie)
774
movie->abort_request = 1;
775
SDL_WaitThread(movie->decode_thread, NULL);
776
if(movie->sourcename) {
777
free((void*)movie->sourcename);
782
void ffmovie_play(FFMovie *movie) {
786
void ffmovie_stop(FFMovie *movie) {
788
/*should force blit of current frame to source*/
789
/*even better, to rgb not just yuv*/
792
void ffmovie_pause(FFMovie *movie) {
800
int ffmovie_finished(FFMovie *movie) {
801
return movie->context == NULL;
805
void ffmovie_setdisplay(FFMovie *movie, SDL_Surface *dest, SDL_Rect *rect)
809
if(!movie->video_st || movie->abort_request || movie->context==NULL) {
810
/*This movie has no video stream, or finished*/
814
SDL_LockMutex(movie->dest_mutex);
816
if(movie->dest_overlay) {
817
/*clean any existing overlay*/
818
SDL_FreeYUVOverlay(movie->dest_overlay);
819
movie->dest_overlay = NULL;
824
movie->dest_overlay = NULL;
827
movie->dest_rect.x = rect->x;
828
movie->dest_rect.y = rect->y;
829
movie->dest_rect.w = rect->w;
830
movie->dest_rect.h = rect->h;
832
movie->dest_rect.x = 0;
833
movie->dest_rect.y = 0;
834
movie->dest_rect.w = 0;
835
movie->dest_rect.h = 0;
837
if(movie->dest_rect.w == 0) {
838
movie->dest_rect.w = MIN(movie->video_st->codec.width, dest->w);
840
if(movie->dest_rect.h == 0) {
841
movie->dest_rect.h = MIN(movie->video_st->codec.height, dest->h);
845
/* XXX: use generic function */
846
/* XXX: disable overlay if no hardware acceleration or if RGB format */
847
switch(movie->video_st->codec.pix_fmt) {
848
case PIX_FMT_YUV420P:
849
case PIX_FMT_YUV422P:
850
case PIX_FMT_YUV444P:
852
case PIX_FMT_YUV410P:
853
case PIX_FMT_YUV411P:
861
movie->dest_surface = dest;
862
movie->dest_overlay = SDL_CreateYUVOverlay(
863
movie->video_st->codec.width,
864
movie->video_st->codec.height,
865
SDL_YV12_OVERLAY, dest);
868
SDL_UnlockMutex(movie->dest_mutex);
870
/*set display time to now, force redraw*/
871
movie->dest_showtime = get_master_clock(movie);
875
void ffmovie_setvolume(FFMovie *movie, int volume) {
876
if(movie->audio_st) {
877
movie->audio_volume = volume;
878
/*note, i'll need to multiply the sound data myself*/
884
void ffmovie_abortall() {
885
Global_abort_all = 1;
886
while(Global_num_active > 0) {
889
Global_abort_all = 0;
893
FFMovie *ffmovie_reopen(FFMovie *movie) {
894
const char* filename;
895
SDL_Overlay *dest_overlay;
896
SDL_Surface *dest_surface;
898
int waspaused = movie->paused;
900
filename = movie->sourcename;
901
movie->sourcename = NULL;
906
SDL_LockMutex(movie->dest_mutex);
907
dest_overlay = movie->dest_overlay;
908
dest_surface = movie->dest_surface;
909
dest_rect = movie->dest_rect;
910
movie->dest_overlay = NULL;
911
movie->dest_surface = NULL;
912
SDL_UnlockMutex(movie->dest_mutex);
914
ffmovie_close(movie);
916
movie = ffmovie_open(filename);
917
free((void*)filename);
921
SDL_LockMutex(movie->dest_mutex);
922
movie->dest_overlay = dest_overlay;
923
movie->dest_surface = dest_surface;
924
movie->dest_rect = dest_rect;
925
SDL_UnlockMutex(movie->dest_mutex);