From 54a4a25fe9d4504ba60fe40dc15744403a4680f9 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 5 Jul 2014 17:00:23 +0200 Subject: tv: move demuxer parts to separate file Now all demuxer implementations (at least demuxer API-wise) are in the demux directory. --- demux/demux_tv.c | 251 +++++++++++++++++++++++++++++++++++++++++++++++++++++ old-makefile | 3 +- options/options.c | 1 - stream/tv.c | 255 ++---------------------------------------------------- stream/tv.h | 8 ++ wscript_build.py | 1 + 6 files changed, 267 insertions(+), 252 deletions(-) create mode 100644 demux/demux_tv.c diff --git a/demux/demux_tv.c b/demux/demux_tv.c new file mode 100644 index 0000000000..54aaae1786 --- /dev/null +++ b/demux/demux_tv.c @@ -0,0 +1,251 @@ +#include + +#include "common/common.h" +#include "common/msg.h" + +#include "options/m_option.h" +#include "options/m_config.h" +#include "options/options.h" + +#include "demux.h" + +#include "audio/format.h" +#include "video/img_fourcc.h" + +#include "stream/stream.h" +#include "stream/tv.h" + +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) + return -1; + + tv_param_t *params = m_sub_options_copy(demuxer, &tv_params_conf, + demuxer->opts->tv_params); + struct tv_stream_params *sparams = demuxer->stream->priv; + if (sparams->channel && sparams->channel[0]) { + talloc_free(params->channel); + params->channel = talloc_strdup(NULL, sparams->channel); + } + if (sparams->input >= 0) + params->input = sparams->input; + + assert(demuxer->priv==NULL); + if(!(tvh=tv_begin(params, demuxer->log))) return -1; + if (!tvh->functions->init(tvh->priv)) return -1; + + tvh->demuxer = demuxer; + + if (!open_tv(tvh)){ + tv_uninit(tvh); + return -1; + } + funcs = tvh->functions; + demuxer->priv=tvh; + + struct sh_stream *sh_v = new_sh_stream(demuxer, 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"; + } else { + sh_v->codec = "rawvideo"; + sh_v->format = fourcc; + } + + /* set FPS and FRAMETIME */ + + if(!sh_video->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; + } + + if (tvh->tv_param->fps != -1.0f) + sh_video->fps = tvh->tv_param->fps; + + /* If playback only mode, go to immediate mode, fail silently */ + if(tvh->tv_param->immediate == 1) + { + funcs->control(tvh->priv, TVI_CONTROL_IMMEDIATE, 0); + tvh->tv_param->audio = 0; + } + + /* set width */ + funcs->control(tvh->priv, TVI_CONTROL_VID_GET_WIDTH, &sh_video->disp_w); + + /* set height */ + funcs->control(tvh->priv, TVI_CONTROL_VID_GET_HEIGHT, &sh_video->disp_h); + + demuxer->seekable = 0; + + /* here comes audio init */ + if (tvh->tv_param->audio && funcs->control(tvh->priv, TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE) + { + int audio_format; + + /* yeah, audio is present */ + + funcs->control(tvh->priv, TVI_CONTROL_AUD_SET_SAMPLERATE, + &tvh->tv_param->audiorate); + + if (funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_FORMAT, &audio_format) != TVI_CONTROL_TRUE) + goto no_audio; + + switch(audio_format) + { + case AF_FORMAT_U8: + case AF_FORMAT_S8: + case AF_FORMAT_U16_LE: + case AF_FORMAT_U16_BE: + case AF_FORMAT_S16_LE: + case AF_FORMAT_S16_BE: + case AF_FORMAT_S32_LE: + case AF_FORMAT_S32_BE: + break; + case AF_FORMAT_MPEG2: + default: + MP_ERR(tvh, "Audio type '%s' unsupported!\n", + af_fmt_to_str(audio_format)); + goto no_audio; + } + + struct sh_stream *sh_a = new_sh_stream(demuxer, 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; + funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_CHANNELS, + &nchannels); + mp_chmap_from_channels(&sh_audio->channels, nchannels); + + sh_a->codec = "mp-pcm"; + sh_a->format = audio_format; + + int samplesize = af_fmt2bps(audio_format); + int block_align = samplesize * sh_audio->channels.num; + int bytes_per_second = sh_audio->samplerate * block_align; + + sh_audio->bitrate = bytes_per_second * 8; + + // emulate WF for win32 codecs: + sh_audio->wf = talloc_zero(sh_audio, MP_WAVEFORMATEX); + sh_audio->wf->wFormatTag = sh_a->format; + sh_audio->wf->nChannels = sh_audio->channels.num; + sh_audio->wf->wBitsPerSample = samplesize * 8; + sh_audio->wf->nSamplesPerSec = sh_audio->samplerate; + sh_audio->wf->nBlockAlign = block_align; + sh_audio->wf->nAvgBytesPerSec = bytes_per_second; + + MP_VERBOSE(tvh, " TV audio: %d channels, %d bits, %d Hz\n", + sh_audio->wf->nChannels, sh_audio->wf->wBitsPerSample, + sh_audio->wf->nSamplesPerSec); + } +no_audio: + + if(!(funcs->start(tvh->priv))){ + // start failed :( + tv_uninit(tvh); + return -1; + } + + /* set color eq */ + tv_set_color_options(tvh, TV_COLOR_BRIGHTNESS, tvh->tv_param->brightness); + tv_set_color_options(tvh, TV_COLOR_HUE, tvh->tv_param->hue); + tv_set_color_options(tvh, TV_COLOR_SATURATION, tvh->tv_param->saturation); + tv_set_color_options(tvh, TV_COLOR_CONTRAST, tvh->tv_param->contrast); + + if(tvh->tv_param->gain!=-1) + if(funcs->control(tvh->priv,TVI_CONTROL_VID_SET_GAIN,&tvh->tv_param->gain)!=TVI_CONTROL_TRUE) + MP_WARN(tvh, "Unable to set gain control!\n"); + + return 0; +} + +static void demux_close_tv(demuxer_t *demuxer) +{ + tvi_handle_t *tvh=(tvi_handle_t*)(demuxer->priv); + if (!tvh) return; + tv_uninit(tvh); + free(tvh); + demuxer->priv=NULL; +} + +static int demux_tv_fill_buffer(demuxer_t *demux) +{ + tvi_handle_t *tvh=(tvi_handle_t*)(demux->priv); + demux_packet_t* dp; + 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]; + if (!demux_has_packet(sh) && + demuxer_stream_is_selected(demux, sh)) + { + if (sh->type == STREAM_AUDIO) + want_audio = sh; + if (sh->type == STREAM_VIDEO) + want_video = sh; + } + } + + /* ================== ADD AUDIO PACKET =================== */ + + if (want_audio && tvh->tv_param->audio && + tvh->functions->control(tvh->priv, + TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE) + { + len = tvh->functions->get_audio_framesize(tvh->priv); + + dp=new_demux_packet(len); + dp->keyframe = true; + dp->pts=tvh->functions->grab_audio_frame(tvh->priv, dp->buffer,len); + demux_add_packet(want_audio, dp); + } + + /* ================== ADD VIDEO PACKET =================== */ + + if (want_video && tvh->functions->control(tvh->priv, + TVI_CONTROL_IS_VIDEO, 0) == TVI_CONTROL_TRUE) + { + len = tvh->functions->get_video_framesize(tvh->priv); + dp=new_demux_packet(len); + dp->keyframe = true; + dp->pts=tvh->functions->grab_video_frame(tvh->priv, dp->buffer, len); + demux_add_packet(want_video, dp); + } + + if (tvh->tv_param->scan) tv_scan(tvh); + return 1; +} + +static int demux_tv_control(demuxer_t *demuxer, int cmd, void *arg) +{ + tvi_handle_t *tvh=(tvi_handle_t*)(demuxer->priv); + if (cmd != DEMUXER_CTRL_STREAM_CTRL) + return DEMUXER_CTRL_NOTIMPL; + struct demux_ctrl_stream_ctrl *ctrl = arg; + ctrl->res = tv_stream_control(tvh, ctrl->ctrl, ctrl->arg); + return DEMUXER_CTRL_OK; +} + +const demuxer_desc_t demuxer_desc_tv = { + .name = "tv", + .desc = "TV card demuxer", + .fill_buffer = demux_tv_fill_buffer, + .control = demux_tv_control, + .open = demux_open_tv, + .close = demux_close_tv, +}; diff --git a/old-makefile b/old-makefile index 9c372c9b25..c5d8e6a223 100644 --- a/old-makefile +++ b/old-makefile @@ -50,7 +50,8 @@ SOURCES-$(MPG123) += audio/decode/ad_mpg123.c SOURCES-$(PVR) += stream/stream_pvr.c SOURCES-$(TV) += stream/stream_tv.c stream/tv.c \ - stream/frequencies.c stream/tvi_dummy.c + stream/frequencies.c stream/tvi_dummy.c \ + demux/demux_tv.c SOURCES-$(TV_V4L2) += stream/tvi_v4l2.c stream/audio_in.c SOURCES-$(DUMMY_OSD) += sub/osd_dummy.c diff --git a/options/options.c b/options/options.c index bf4db25321..84eda8db64 100644 --- a/options/options.c +++ b/options/options.c @@ -38,7 +38,6 @@ #include "m_option.h" #include "common/common.h" #include "stream/stream.h" -#include "stream/tv.h" #include "video/csputils.h" #include "sub/osd.h" #include "audio/mixer.h" diff --git a/stream/tv.c b/stream/tv.c index 8b33484966..dc50576793 100644 --- a/stream/tv.c +++ b/stream/tv.c @@ -44,8 +44,6 @@ #include "options/options.h" #include "stream.h" -#include "demux/demux.h" -#include "demux/stheader.h" #include "audio/format.h" #include "video/img_fourcc.h" @@ -191,7 +189,7 @@ static int tv_set_freq_float(tvi_handle_t *tvh, float freq) return tv_set_freq(tvh, freq/1000.0*16); } -static void tv_scan(tvi_handle_t *tvh) +void tv_scan(tvi_handle_t *tvh) { unsigned int now; struct CHANLIST cl; @@ -281,63 +279,6 @@ static void tv_scan(tvi_handle_t *tvh) } } -/* ================== DEMUX_TV ===================== */ -/* - Return value: - 0 = EOF(?) or no stream - 1 = successfully read a packet -*/ -/* fill demux->video and demux->audio */ - -static int demux_tv_fill_buffer(demuxer_t *demux) -{ - tvi_handle_t *tvh=(tvi_handle_t*)(demux->priv); - demux_packet_t* dp; - 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]; - if (!demux_has_packet(sh) && - demuxer_stream_is_selected(demux, sh)) - { - if (sh->type == STREAM_AUDIO) - want_audio = sh; - if (sh->type == STREAM_VIDEO) - want_video = sh; - } - } - - /* ================== ADD AUDIO PACKET =================== */ - - if (want_audio && tvh->tv_param->audio && - tvh->functions->control(tvh->priv, - TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE) - { - len = tvh->functions->get_audio_framesize(tvh->priv); - - dp=new_demux_packet(len); - dp->keyframe = true; - dp->pts=tvh->functions->grab_audio_frame(tvh->priv, dp->buffer,len); - demux_add_packet(want_audio, dp); - } - - /* ================== ADD VIDEO PACKET =================== */ - - if (want_video && tvh->functions->control(tvh->priv, - TVI_CONTROL_IS_VIDEO, 0) == TVI_CONTROL_TRUE) - { - len = tvh->functions->get_video_framesize(tvh->priv); - dp=new_demux_packet(len); - dp->keyframe = true; - dp->pts=tvh->functions->grab_video_frame(tvh->priv, dp->buffer, len); - demux_add_packet(want_video, dp); - } - - if (tvh->tv_param->scan) tv_scan(tvh); - return 1; -} - static int norm_from_string(tvi_handle_t *tvh, char* norm) { const tvi_functions_t *funcs = tvh->functions; @@ -492,7 +433,7 @@ static void set_norm_and_freq(tvi_handle_t *tvh, tv_channels_t *chan) tv_set_freq_float(tvh, chan->freq); } -static int open_tv(tvi_handle_t *tvh) +int open_tv(tvi_handle_t *tvh) { int i; const tvi_functions_t *funcs = tvh->functions; @@ -717,7 +658,7 @@ done: return 1; } -static tvi_handle_t *tv_begin(tv_param_t* tv_param, struct mp_log *log) +tvi_handle_t *tv_begin(tv_param_t* tv_param, struct mp_log *log) { int i; tvi_handle_t* h; @@ -755,7 +696,7 @@ static tvi_handle_t *tv_begin(tv_param_t* tv_param, struct mp_log *log) return NULL; } -static int tv_uninit(tvi_handle_t *tvh) +int tv_uninit(tvi_handle_t *tvh) { int res; if(!tvh) return 1; @@ -768,173 +709,6 @@ static int tv_uninit(tvi_handle_t *tvh) return res; } -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) - return -1; - - tv_param_t *params = m_sub_options_copy(demuxer, &tv_params_conf, - demuxer->opts->tv_params); - struct tv_stream_params *sparams = demuxer->stream->priv; - if (sparams->channel && sparams->channel[0]) { - talloc_free(params->channel); - params->channel = talloc_strdup(NULL, sparams->channel); - } - if (sparams->input >= 0) - params->input = sparams->input; - - assert(demuxer->priv==NULL); - if(!(tvh=tv_begin(params, demuxer->log))) return -1; - if (!tvh->functions->init(tvh->priv)) return -1; - - tvh->demuxer = demuxer; - - if (!open_tv(tvh)){ - tv_uninit(tvh); - return -1; - } - funcs = tvh->functions; - demuxer->priv=tvh; - - struct sh_stream *sh_v = new_sh_stream(demuxer, 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"; - } else { - sh_v->codec = "rawvideo"; - sh_v->format = fourcc; - } - - /* set FPS and FRAMETIME */ - - if(!sh_video->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; - } - - if (tvh->tv_param->fps != -1.0f) - sh_video->fps = tvh->tv_param->fps; - - /* If playback only mode, go to immediate mode, fail silently */ - if(tvh->tv_param->immediate == 1) - { - funcs->control(tvh->priv, TVI_CONTROL_IMMEDIATE, 0); - tvh->tv_param->audio = 0; - } - - /* set width */ - funcs->control(tvh->priv, TVI_CONTROL_VID_GET_WIDTH, &sh_video->disp_w); - - /* set height */ - funcs->control(tvh->priv, TVI_CONTROL_VID_GET_HEIGHT, &sh_video->disp_h); - - demuxer->seekable = 0; - - /* here comes audio init */ - if (tvh->tv_param->audio && funcs->control(tvh->priv, TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE) - { - int audio_format; - - /* yeah, audio is present */ - - funcs->control(tvh->priv, TVI_CONTROL_AUD_SET_SAMPLERATE, - &tvh->tv_param->audiorate); - - if (funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_FORMAT, &audio_format) != TVI_CONTROL_TRUE) - goto no_audio; - - switch(audio_format) - { - case AF_FORMAT_U8: - case AF_FORMAT_S8: - case AF_FORMAT_U16_LE: - case AF_FORMAT_U16_BE: - case AF_FORMAT_S16_LE: - case AF_FORMAT_S16_BE: - case AF_FORMAT_S32_LE: - case AF_FORMAT_S32_BE: - break; - case AF_FORMAT_MPEG2: - default: - MP_ERR(tvh, "Audio type '%s' unsupported!\n", - af_fmt_to_str(audio_format)); - goto no_audio; - } - - struct sh_stream *sh_a = new_sh_stream(demuxer, 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; - funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_CHANNELS, - &nchannels); - mp_chmap_from_channels(&sh_audio->channels, nchannels); - - sh_a->codec = "mp-pcm"; - sh_a->format = audio_format; - - int samplesize = af_fmt2bps(audio_format); - int block_align = samplesize * sh_audio->channels.num; - int bytes_per_second = sh_audio->samplerate * block_align; - - sh_audio->bitrate = bytes_per_second * 8; - - // emulate WF for win32 codecs: - sh_audio->wf = talloc_zero(sh_audio, MP_WAVEFORMATEX); - sh_audio->wf->wFormatTag = sh_a->format; - sh_audio->wf->nChannels = sh_audio->channels.num; - sh_audio->wf->wBitsPerSample = samplesize * 8; - sh_audio->wf->nSamplesPerSec = sh_audio->samplerate; - sh_audio->wf->nBlockAlign = block_align; - sh_audio->wf->nAvgBytesPerSec = bytes_per_second; - - MP_VERBOSE(tvh, " TV audio: %d channels, %d bits, %d Hz\n", - sh_audio->wf->nChannels, sh_audio->wf->wBitsPerSample, - sh_audio->wf->nSamplesPerSec); - } -no_audio: - - if(!(funcs->start(tvh->priv))){ - // start failed :( - tv_uninit(tvh); - return -1; - } - - /* set color eq */ - tv_set_color_options(tvh, TV_COLOR_BRIGHTNESS, tvh->tv_param->brightness); - tv_set_color_options(tvh, TV_COLOR_HUE, tvh->tv_param->hue); - tv_set_color_options(tvh, TV_COLOR_SATURATION, tvh->tv_param->saturation); - tv_set_color_options(tvh, TV_COLOR_CONTRAST, tvh->tv_param->contrast); - - if(tvh->tv_param->gain!=-1) - if(funcs->control(tvh->priv,TVI_CONTROL_VID_SET_GAIN,&tvh->tv_param->gain)!=TVI_CONTROL_TRUE) - MP_WARN(tvh, "Unable to set gain control!\n"); - - return 0; -} - -static void demux_close_tv(demuxer_t *demuxer) -{ - tvi_handle_t *tvh=(tvi_handle_t*)(demuxer->priv); - if (!tvh) return; - tv_uninit(tvh); - free(tvh); - demuxer->priv=NULL; -} - int tv_set_color_options(tvi_handle_t *tvh, int opt, int value) { const tvi_functions_t *funcs = tvh->functions; @@ -1171,7 +945,7 @@ int tv_step_norm(tvi_handle_t *tvh) return 1; } -static int tv_stream_control(tvi_handle_t *tvh, int cmd, void *arg) +int tv_stream_control(tvi_handle_t *tvh, int cmd, void *arg) { switch (cmd) { case STREAM_CTRL_TV_SET_SCAN: @@ -1214,22 +988,3 @@ static int tv_stream_control(tvi_handle_t *tvh, int cmd, void *arg) } return STREAM_UNSUPPORTED; } - -static int demux_tv_control(demuxer_t *demuxer, int cmd, void *arg) -{ - tvi_handle_t *tvh=(tvi_handle_t*)(demuxer->priv); - if (cmd != DEMUXER_CTRL_STREAM_CTRL) - return DEMUXER_CTRL_NOTIMPL; - struct demux_ctrl_stream_ctrl *ctrl = arg; - ctrl->res = tv_stream_control(tvh, ctrl->ctrl, ctrl->arg); - return DEMUXER_CTRL_OK; -} - -const demuxer_desc_t demuxer_desc_tv = { - .name = "tv", - .desc = "TV card demuxer", - .fill_buffer = demux_tv_fill_buffer, - .control = demux_tv_control, - .open = demux_open_tv, - .close = demux_close_tv, -}; diff --git a/stream/tv.h b/stream/tv.h index d6d75e8ee4..0f9fa1defb 100644 --- a/stream/tv.h +++ b/stream/tv.h @@ -231,4 +231,12 @@ void tv_free_handle(tvi_handle_t *h); #define TV_NORM_PALN 6 #define TV_NORM_NTSCJP 7 +int tv_uninit(tvi_handle_t *tvh); +void tv_scan(tvi_handle_t *tvh); +int open_tv(tvi_handle_t *tvh); +tvi_handle_t *tv_begin(tv_param_t* tv_param, struct mp_log *log); +int tv_stream_control(tvi_handle_t *tvh, int cmd, void *arg); + +extern const struct m_sub_options tv_params_conf; + #endif /* MPLAYER_TV_H */ diff --git a/wscript_build.py b/wscript_build.py index 95ca54b187..62446d1907 100644 --- a/wscript_build.py +++ b/wscript_build.py @@ -183,6 +183,7 @@ def build(ctx): ( "demux/demux_playlist.c" ), ( "demux/demux_raw.c" ), ( "demux/demux_subreader.c" ), + ( "demux/demux_tv.c", "tv" ), ( "demux/ebml.c" ), ( "demux/mf.c" ), ( "demux/packet.c" ), -- cgit v1.2.3