From 41500b69fd2f67541904bb7b146d5ba3ee472d21 Mon Sep 17 00:00:00 2001 From: Torsten Jager Date: Sat, 13 Aug 2011 18:02:30 +0200 Subject: VP8 support --- src/xine-engine/buffer.h | 1 + src/xine-engine/buffer_types.c | 8 ++++++++ 2 files changed, 9 insertions(+) (limited to 'src/xine-engine') diff --git a/src/xine-engine/buffer.h b/src/xine-engine/buffer.h index 034f6552a..9198ff103 100644 --- a/src/xine-engine/buffer.h +++ b/src/xine-engine/buffer.h @@ -189,6 +189,7 @@ extern "C" { #define BUF_VIDEO_VC1 0x02650000 #define BUF_VIDEO_VMNC 0x02660000 #define BUF_VIDEO_SNOW 0x02670000 +#define BUF_VIDEO_VP8 0x02680000 /* audio buffer types: (please keep in sync with buffer_types.c) */ diff --git a/src/xine-engine/buffer_types.c b/src/xine-engine/buffer_types.c index e6b846d64..050043c64 100644 --- a/src/xine-engine/buffer_types.c +++ b/src/xine-engine/buffer_types.c @@ -789,6 +789,14 @@ static const video_db_t video_db[] = { BUF_VIDEO_SNOW, "Snow" }, +{ + { + ME_FOURCC('V','P','8','0'), + 0 + }, + BUF_VIDEO_VP8, + "On2 VP8" +}, { { 0 }, 0, "last entry" } }; -- cgit v1.2.3 From 078eade9b4a427497250ca567ebe1865ecd47a8f Mon Sep 17 00:00:00 2001 From: Torsten Jager Date: Mon, 22 Aug 2011 11:49:01 +0200 Subject: Audio crash fix Audio decoder loop creates a sorted map of available audio channels on the fly. If neither user nor dvdnav intervene, it will pass the first (= lowest index) audio channel to decoders. Now imagine a TV recording with 2 audio channels: audio.0: eac3 5.1 (fra) audio.1: eac3 stereo (qaa) By chance, first audio frame to be demuxed is for channel #1. Track map will be [0]: eac3, channel 1 Audio loop opens ffmpeg audio decoder / stereo out. Fine. Then, first frame for channel #0 comes in. [0]: eac3, channel 0 [1]: eac3, channel 1 Both are same codec, so audio loop just switches to channel 0 without further notice. Audio decoder then runs into a mem leak, or worse, crashes audio out who still thinks we're only stereo. Whenever we insert something at track map index 0, and its going to be auto-selected later, reset current codec type. This forces a clean decoder/output switch. --- src/xine-engine/audio_decoder.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/xine-engine') diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c index 3d5ef7e6f..10c20f231 100644 --- a/src/xine-engine/audio_decoder.c +++ b/src/xine-engine/audio_decoder.c @@ -283,6 +283,9 @@ static void *audio_decoder_loop (void *stream_gen) { } stream->audio_track_map[i] = buf->type; stream->audio_track_map_entries++; + /* implicit channel change - reopen decoder below */ + if ((i == 0) && (audio_channel_user == -1) && (stream->audio_channel_auto < 0)) + stream->audio_decoder_streamtype = -1; ui_event.type = XINE_EVENT_UI_CHANNELS_CHANGED; ui_event.data_length = 0; -- cgit v1.2.3 From 7e6f30b0062375c30db8e67b464c7fe003ed15d5 Mon Sep 17 00:00:00 2001 From: Torsten Jager Date: Mon, 22 Aug 2011 11:50:16 +0200 Subject: UI freeze fix xine_play () gets suspended after start or seek until first frame gets displayed. This often wont work on slow machines when first frame gets dropped because its too old. Consequently, UI freezes for full 10 seconds. Let's wake up xine_play when this happens as well. OK, this is a luxury convenience fix ;-) --- src/xine-engine/video_out.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'src/xine-engine') diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index 0bbf977f2..f3e24537e 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.c @@ -802,7 +802,7 @@ static void expire_frames (vos_t *this, int64_t cur_vpts) { while (img) { - if (img->is_first) { + if (img->is_first > 0) { lprintf("expire_frames: first_frame !\n"); /* @@ -819,6 +819,8 @@ static void expire_frames (vos_t *this, int64_t cur_vpts) { img->vpts = cur_vpts + FIRST_FRAME_POLL_DELAY; } img->is_first--; + /* make sure to wake up xine_play even if this first frame gets discarded */ + if (img->is_first == 0) img->is_first = -1; break; } @@ -848,6 +850,24 @@ static void expire_frames (vos_t *this, int64_t cur_vpts) { pthread_mutex_lock( &img->stream->current_extra_info_lock ); _x_extra_info_merge( img->stream->current_extra_info, img->extra_info ); pthread_mutex_unlock( &img->stream->current_extra_info_lock ); + /* wake up xine_play now if we just discarded first frame */ + if (img->is_first != 0) { + xine_list_iterator_t ite; + pthread_mutex_lock (&this->streams_lock); + for (ite = xine_list_front(this->streams); ite; + ite = xine_list_next(this->streams, ite)) { + xine_stream_t *stream = xine_list_get_value (this->streams, ite); + if (stream == XINE_ANON_STREAM) continue; + pthread_mutex_lock (&stream->first_frame_lock); + if (stream->first_frame_flag) { + stream->first_frame_flag = 0; + pthread_cond_broadcast (&stream->first_frame_reached); + } + pthread_mutex_unlock (&stream->first_frame_lock); + } + pthread_mutex_unlock(&this->streams_lock); + xine_log (this->xine, XINE_LOG_MSG, _("video_out: just discarded first frame after seek\n")); + } } /* when flushing frames, keep the first one as backup */ -- cgit v1.2.3 From edb68926aced0739f3e62ea2501bc32326c02f86 Mon Sep 17 00:00:00 2001 From: Torsten Jager Date: Mon, 22 Aug 2011 11:51:20 +0200 Subject: Video deadlock fix When watching TV with Kaffeine I frequently had complete engine lockups. Multiple mutexes were waiting on each other. net_buf_ctrl requires the demuxer to keep running while playback is still paused. The diff might look a bit confusing. Basically, all I did was to replace phtread_mutex_lock (); ... pthread_mutex_unlock (); with if (pthread_mutex_trylock ()) { ... pthread_mutex_unlock (); } at a place where it does the least damage. --- src/xine-engine/video_out.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) (limited to 'src/xine-engine') diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index f3e24537e..a6d39f23f 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.c @@ -572,25 +572,28 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) { * check for first frame after seek and mark it */ img->is_first = 0; - pthread_mutex_lock(&this->streams_lock); - for (ite = xine_list_front(this->streams); ite; - ite = xine_list_next(this->streams, ite)) { - stream = xine_list_get_value(this->streams, ite); - if (stream == XINE_ANON_STREAM) continue; - pthread_mutex_lock (&stream->first_frame_lock); - if (stream->first_frame_flag == 2) { - if (this->grab_only) { - stream->first_frame_flag = 0; - pthread_cond_broadcast(&stream->first_frame_reached); - } else - stream->first_frame_flag = 1; - img->is_first = FIRST_FRAME_MAX_POLL; - - lprintf ("get_next_video_frame first_frame_reached\n"); + /* avoid a complex deadlock situation caused by net_buf_control */ + if (!pthread_mutex_trylock(&this->streams_lock)) { + for (ite = xine_list_front(this->streams); ite; + ite = xine_list_next(this->streams, ite)) { + stream = xine_list_get_value(this->streams, ite); + if (stream == XINE_ANON_STREAM) continue; + pthread_mutex_lock (&stream->first_frame_lock); + if (stream->first_frame_flag == 2) { + if (this->grab_only) { + stream->first_frame_flag = 0; + pthread_cond_broadcast(&stream->first_frame_reached); + } else { + stream->first_frame_flag = 1; + } + img->is_first = FIRST_FRAME_MAX_POLL; + + lprintf ("get_next_video_frame first_frame_reached\n"); + } + pthread_mutex_unlock (&stream->first_frame_lock); } - pthread_mutex_unlock (&stream->first_frame_lock); + pthread_mutex_unlock(&this->streams_lock); } - pthread_mutex_unlock(&this->streams_lock); if (!img_already_locked) vo_frame_inc_lock( img ); -- cgit v1.2.3