From f9ba1a3ddf5186cb31c2715e3293eef70575a9ee Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 23 Dec 2015 21:44:53 +0100 Subject: demux: remove weird tripple-buffering for the sh_stream list The demuxer infrastructure was originally single-threaded. To make it suitable for multithreading (specifically, demuxing and decoding on separate threads), some sort of tripple-buffering was introduced. There are separate "struct demuxer" allocations. The demuxer thread sets the state on d_thread. If anything changes, the state is copied to d_buffer (the copy is protected by a lock), and the decoder thread is notified. Then the decoder thread copies the state from d_buffer to d_user (again while holding a lock). This avoids the need for locking in the demuxer/decoder code itself (only demux.c needs an internal, "invisible" lock.) Remove the streams/num_streams fields from this tripple-buffering schema. Move them to the internal struct, and protect them with the internal lock. Use accessors for read access outside of demux.c. Other than replacing all field accesses with accessors, this separates allocating and adding sh_streams. This is needed to avoid race conditions. Before this change, this was awkwardly handled by first initializing the sh_stream, and then sending a stream change event. Now the stream is allocated, then initialized, and then declared as immutable and added (at which point it becomes visible to the decoder thread immediately). This change is useful for PR #2626. And eventually, we should probably get entirely of the tripple buffering, and this makes a nice first step. --- demux/demux_tv.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'demux/demux_tv.c') diff --git a/demux/demux_tv.c b/demux/demux_tv.c index ab584874cb..a2d06591e0 100644 --- a/demux/demux_tv.c +++ b/demux/demux_tv.c @@ -50,7 +50,7 @@ static int demux_open_tv(demuxer_t *demuxer, enum demux_check check) funcs = tvh->functions; demuxer->priv=tvh; - struct sh_stream *sh_v = new_sh_stream(demuxer, STREAM_VIDEO); + struct sh_stream *sh_v = demux_alloc_sh_stream(STREAM_VIDEO); sh_video = sh_v->video; /* get IMAGE FORMAT */ @@ -89,6 +89,8 @@ static int demux_open_tv(demuxer_t *demuxer, enum demux_check check) /* set height */ funcs->control(tvh->priv, TVI_CONTROL_VID_GET_HEIGHT, &sh_video->disp_h); + demux_add_sh_stream(demuxer, sh_v); + demuxer->seekable = 0; /* here comes audio init */ @@ -115,7 +117,7 @@ static int demux_open_tv(demuxer_t *demuxer, enum demux_check check) goto no_audio; } - struct sh_stream *sh_a = new_sh_stream(demuxer, STREAM_AUDIO); + struct sh_stream *sh_a = demux_alloc_sh_stream(STREAM_AUDIO); sh_audio = sh_a->audio; funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLERATE, @@ -128,6 +130,8 @@ static int demux_open_tv(demuxer_t *demuxer, enum demux_check check) // s16ne mp_set_pcm_codec(sh_a, true, false, 16, BYTE_ORDER == BIG_ENDIAN); + demux_add_sh_stream(demuxer, sh_a); + MP_VERBOSE(tvh, " TV audio: %d channels, %d bits, %d Hz\n", nchannels, 16, sh_audio->samplerate); } @@ -168,8 +172,9 @@ static int demux_tv_fill_buffer(demuxer_t *demux) unsigned int len=0; struct sh_stream *want_audio = NULL, *want_video = NULL; - for (int n = 0; n < demux->num_streams; n++) { - struct sh_stream *sh = demux->streams[n]; + int num_streams = demux_get_num_stream(demux); + for (int n = 0; n < num_streams; n++) { + struct sh_stream *sh = demux_get_stream(demux, n); if (!demux_has_packet(sh) && demux_stream_is_selected(sh)) { if (sh->type == STREAM_AUDIO) want_audio = sh; -- cgit v1.2.3 From 671df54e4dcf0675c335483d26f7f6ff9baaf76a Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 12 Jan 2016 23:48:19 +0100 Subject: demux: merge sh_video/sh_audio/sh_sub This is mainly a refactor. I'm hoping it will make some things easier in the future due to cleanly separating codec metadata and stream metadata. Also, declare that the "codec" field can not be NULL anymore. demux.c will set it to "" if it's NULL when added. This gets rid of a corner case everything had to handle, but which rarely happened. --- demux/demux_tv.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'demux/demux_tv.c') diff --git a/demux/demux_tv.c b/demux/demux_tv.c index a2d06591e0..4f1e3ac1c2 100644 --- a/demux/demux_tv.c +++ b/demux/demux_tv.c @@ -20,8 +20,6 @@ static int demux_open_tv(demuxer_t *demuxer, enum demux_check check) { tvi_handle_t *tvh; - sh_video_t *sh_video; - sh_audio_t *sh_audio = NULL; const tvi_functions_t *funcs; if (check > DEMUX_CHECK_REQUEST || demuxer->stream->type != STREAMTYPE_TV) @@ -51,30 +49,29 @@ static int demux_open_tv(demuxer_t *demuxer, enum demux_check check) demuxer->priv=tvh; struct sh_stream *sh_v = demux_alloc_sh_stream(STREAM_VIDEO); - sh_video = sh_v->video; /* get IMAGE FORMAT */ int fourcc; funcs->control(tvh->priv, TVI_CONTROL_VID_GET_FORMAT, &fourcc); if (fourcc == MP_FOURCC_MJPEG) { - sh_v->codec = "mjpeg"; + sh_v->codec->codec = "mjpeg"; } else { - sh_v->codec = "rawvideo"; - sh_v->codec_tag = fourcc; + sh_v->codec->codec = "rawvideo"; + sh_v->codec->codec_tag = fourcc; } /* set FPS and FRAMETIME */ - if(!sh_video->fps) + if(!sh_v->codec->fps) { float tmp; if (funcs->control(tvh->priv, TVI_CONTROL_VID_GET_FPS, &tmp) != TVI_CONTROL_TRUE) - sh_video->fps = 25.0f; /* on PAL */ - else sh_video->fps = tmp; + sh_v->codec->fps = 25.0f; /* on PAL */ + else sh_v->codec->fps = tmp; } if (tvh->tv_param->fps != -1.0f) - sh_video->fps = tvh->tv_param->fps; + sh_v->codec->fps = tvh->tv_param->fps; /* If playback only mode, go to immediate mode, fail silently */ if(tvh->tv_param->immediate == 1) @@ -84,10 +81,10 @@ static int demux_open_tv(demuxer_t *demuxer, enum demux_check check) } /* set width */ - funcs->control(tvh->priv, TVI_CONTROL_VID_GET_WIDTH, &sh_video->disp_w); + funcs->control(tvh->priv, TVI_CONTROL_VID_GET_WIDTH, &sh_v->codec->disp_w); /* set height */ - funcs->control(tvh->priv, TVI_CONTROL_VID_GET_HEIGHT, &sh_video->disp_h); + funcs->control(tvh->priv, TVI_CONTROL_VID_GET_HEIGHT, &sh_v->codec->disp_h); demux_add_sh_stream(demuxer, sh_v); @@ -118,22 +115,21 @@ static int demux_open_tv(demuxer_t *demuxer, enum demux_check check) } struct sh_stream *sh_a = demux_alloc_sh_stream(STREAM_AUDIO); - sh_audio = sh_a->audio; funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLERATE, - &sh_audio->samplerate); - int nchannels = sh_audio->channels.num; + &sh_a->codec->samplerate); + int nchannels = sh_a->codec->channels.num; funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_CHANNELS, &nchannels); - mp_chmap_from_channels(&sh_audio->channels, nchannels); + mp_chmap_from_channels(&sh_a->codec->channels, nchannels); // s16ne - mp_set_pcm_codec(sh_a, true, false, 16, BYTE_ORDER == BIG_ENDIAN); + mp_set_pcm_codec(sh_a->codec, true, false, 16, BYTE_ORDER == BIG_ENDIAN); demux_add_sh_stream(demuxer, sh_a); MP_VERBOSE(tvh, " TV audio: %d channels, %d bits, %d Hz\n", - nchannels, 16, sh_audio->samplerate); + nchannels, 16, sh_a->codec->samplerate); } no_audio: -- cgit v1.2.3