// Check for unsupported formats static int check_format(int format) { char buf[256]; if ((format & AF_FORMAT_SPECIAL_MASK) == 0) return AF_OK; mp_msg(MSGT_AFILTER, MSGL_ERR, "[format] Sample format %s not yet supported \n", af_fmt2str(format,buf,256)); return AF_ERROR; }
// Check for unsupported formats static int check_format(int format) { char buf[256]; switch(format & AF_FORMAT_SPECIAL_MASK){ case(AF_FORMAT_IMA_ADPCM): case(AF_FORMAT_MPEG2): case(AF_FORMAT_AC3): mp_msg(MSGT_AFILTER, MSGL_ERR, "[format] Sample format %s not yet supported \n", af_fmt2str(format,buf,256)); return AF_ERROR; } return AF_OK; }
enum AVSampleFormat affmt2samplefmt(int fmt) { char str[50]; int i; enum AVSampleFormat sample_fmt; for (i = 0; samplefmt_conversion_map[i].fmt; i++) if (samplefmt_conversion_map[i].fmt == fmt) break; sample_fmt = samplefmt_conversion_map[i].sample_fmt; if (sample_fmt == AV_SAMPLE_FMT_NONE) mp_msg(MSGT_GLOBAL, MSGL_ERR, "Unsupported format %s\n", af_fmt2str(fmt, str, sizeof(str))); return sample_fmt; }
static int af_open(af_instance_t* af){ af_ac3enc_t *s = calloc(1,sizeof(af_ac3enc_t)); af->control=control; af->uninit=uninit; af->play=play; af->mul=1; af->data=calloc(1,sizeof(af_data_t)); af->setup=s; s->lavc_acodec = avcodec_find_encoder_by_name("ac3"); if (!s->lavc_acodec) { mp_tmsg(MSGT_AFILTER, MSGL_ERR, "Audio LAVC, couldn't find encoder for codec %s.\n", "ac3"); return AF_ERROR; } s->lavc_actx = avcodec_alloc_context3(s->lavc_acodec); if (!s->lavc_actx) { mp_tmsg(MSGT_AFILTER, MSGL_ERR, "Audio LAVC, couldn't allocate context!\n"); return AF_ERROR; } const enum AVSampleFormat *fmts = s->lavc_acodec->sample_fmts; for (int i = 0; ; i++) { if (fmts[i] == AV_SAMPLE_FMT_NONE) { mp_msg(MSGT_AFILTER, MSGL_ERR, "Audio LAVC, encoder doesn't " "support expected sample formats!\n"); return AF_ERROR; } else if (fmts[i] == AV_SAMPLE_FMT_S16) { s->in_sampleformat = AF_FORMAT_S16_NE; s->lavc_actx->sample_fmt = fmts[i]; break; } else if (fmts[i] == AV_SAMPLE_FMT_FLT) { s->in_sampleformat = AF_FORMAT_FLOAT_NE; s->lavc_actx->sample_fmt = fmts[i]; break; } } char buf[100]; mp_msg(MSGT_AFILTER, MSGL_V, "[af_lavcac3enc]: in sample format: %s\n", af_fmt2str(s->in_sampleformat, buf, 100)); s->pending_data_size = AF_NCH * AC3_FRAME_SIZE * af_fmt2bits(s->in_sampleformat) / 8; s->pending_data = malloc(s->pending_data_size); return AF_OK; }
static demuxer_t* demux_open_tv(demuxer_t *demuxer) { tvi_handle_t *tvh; sh_video_t *sh_video; sh_audio_t *sh_audio = NULL; const tvi_functions_t *funcs; demuxer->priv=NULL; if(!(tvh=tv_begin(demuxer->stream->priv))) return NULL; if (!tvh->functions->init(tvh->priv)) return NULL; tvh->demuxer = demuxer; tvh->functions->control(tvh->priv,TVI_CONTROL_VBI_INIT, &(tvh->tv_param->teletext.device)); tvh->functions->control(tvh->priv,TVI_CONTROL_GET_VBI_PTR, &demuxer->teletext); if (!open_tv(tvh)) { tv_uninit(tvh); return NULL; } funcs = tvh->functions; demuxer->priv=tvh; sh_video = new_sh_video(demuxer, 0); /* get IMAGE FORMAT */ funcs->control(tvh->priv, TVI_CONTROL_VID_GET_FORMAT, &sh_video->format); // if (IMGFMT_IS_RGB(sh_video->format) || IMGFMT_IS_BGR(sh_video->format)) // sh_video->format = 0x0; /* 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; sh_video->frametime = 1.0f/sh_video->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->noaudio = 1; } /* disable TV audio if -nosound is present */ if (!demuxer->audio || demuxer->audio->id == -2) { tvh->tv_param->noaudio = 1; } /* 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->video->sh = sh_video; sh_video->ds = demuxer->video; demuxer->video->id = 0; demuxer->seekable = 0; /* here comes audio init */ if (tvh->tv_param->noaudio == 0 && funcs->control(tvh->priv, TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE) { int audio_format; int sh_audio_format; char buf[128]; /* 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: sh_audio_format = 0x1; /* PCM */ break; case AF_FORMAT_IMA_ADPCM: case AF_FORMAT_MU_LAW: case AF_FORMAT_A_LAW: case AF_FORMAT_MPEG2: default: mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_UnsupportedAudioType, af_fmt2str(audio_format, buf, 128), audio_format); goto no_audio; } sh_audio = new_sh_audio(demuxer, 0, NULL); funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLERATE, &sh_audio->samplerate); funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLESIZE, &sh_audio->samplesize); funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_CHANNELS, &sh_audio->channels); sh_audio->format = sh_audio_format; sh_audio->sample_format = audio_format; sh_audio->i_bps = sh_audio->o_bps = sh_audio->samplerate * sh_audio->samplesize * sh_audio->channels; // emulate WF for win32 codecs: sh_audio->wf = malloc(sizeof(*sh_audio->wf)); sh_audio->wf->wFormatTag = sh_audio->format; sh_audio->wf->nChannels = sh_audio->channels; sh_audio->wf->wBitsPerSample = sh_audio->samplesize * 8; sh_audio->wf->nSamplesPerSec = sh_audio->samplerate; sh_audio->wf->nBlockAlign = sh_audio->samplesize * sh_audio->channels; sh_audio->wf->nAvgBytesPerSec = sh_audio->i_bps; mp_msg(MSGT_DECVIDEO, MSGL_V, " TV audio: %d channels, %d bits, %d Hz\n", sh_audio->wf->nChannels, sh_audio->wf->wBitsPerSample, sh_audio->wf->nSamplesPerSec); demuxer->audio->sh = sh_audio; sh_audio->ds = demuxer->audio; demuxer->audio->id = 0; } no_audio: if(!(funcs->start(tvh->priv))) { // start failed :( tv_uninit(tvh); return NULL; } /* 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_msg(MSGT_TV,MSGL_WARN,"Unable to set gain control!\n"); teletext_control(demuxer->teletext,TV_VBI_CONTROL_RESET, &tvh->tv_param->teletext); return demuxer; }
// Initialization and runtime control static int control(struct af_instance_s* af, int cmd, void* arg) { switch(cmd){ case AF_CONTROL_REINIT:{ char buf1[256]; char buf2[256]; af_data_t *data = arg; // Make sure this filter isn't redundant if(af->data->format == data->format && af->data->bps == data->bps) return AF_DETACH; // Allow trivial AC3-endianness conversion if (!AF_FORMAT_IS_AC3(af->data->format) || !AF_FORMAT_IS_AC3(data->format)) // Check for errors in configuration if((AF_OK != check_bps(data->bps)) || (AF_OK != check_format(data->format)) || (AF_OK != check_bps(af->data->bps)) || (AF_OK != check_format(af->data->format))) return AF_ERROR; mp_msg(MSGT_AFILTER, MSGL_V, "[format] Changing sample format from %s to %s\n", af_fmt2str(data->format,buf1,256), af_fmt2str(af->data->format,buf2,256)); af->data->rate = data->rate; af->data->nch = data->nch; af->mul = (double)af->data->bps / data->bps; af->play = play; // set default // look whether only endianness differences are there if ((af->data->format & ~AF_FORMAT_END_MASK) == (data->format & ~AF_FORMAT_END_MASK)) { mp_msg(MSGT_AFILTER, MSGL_V, "[format] Accelerated endianness conversion only\n"); af->play = play_swapendian; } if ((data->format == AF_FORMAT_FLOAT_NE) && (af->data->format == AF_FORMAT_S16_NE)) { mp_msg(MSGT_AFILTER, MSGL_V, "[format] Accelerated %s to %s conversion\n", af_fmt2str(data->format,buf1,256), af_fmt2str(af->data->format,buf2,256)); af->play = play_float_s16; } if ((data->format == AF_FORMAT_S16_NE) && (af->data->format == AF_FORMAT_FLOAT_NE)) { mp_msg(MSGT_AFILTER, MSGL_V, "[format] Accelerated %s to %s conversion\n", af_fmt2str(data->format,buf1,256), af_fmt2str(af->data->format,buf2,256)); af->play = play_s16_float; } return AF_OK; } case AF_CONTROL_COMMAND_LINE:{ int format = af_str2fmt_short(bstr0(arg)); if (format == -1) { mp_msg(MSGT_AFILTER, MSGL_ERR, "[format] %s is not a valid format\n", (char *)arg); return AF_ERROR; } if(AF_OK != af->control(af,AF_CONTROL_FORMAT_FMT | AF_CONTROL_SET,&format)) return AF_ERROR; return AF_OK; } case AF_CONTROL_FORMAT_FMT | AF_CONTROL_SET:{ // Check for errors in configuration if(!AF_FORMAT_IS_AC3(*(int*)arg) && AF_OK != check_format(*(int*)arg)) return AF_ERROR; af->data->format = *(int*)arg; af->data->bps = af_fmt2bits(af->data->format)/8; return AF_OK; } } return AF_UNKNOWN; }
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; demuxer->priv=NULL; if(!(tvh=tv_begin(demuxer->stream->priv))) 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_video->gsh->codec = "mjpeg"; } else { sh_video->gsh->codec = "rawvideo"; sh_video->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->noaudio = 1; } /* 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->noaudio == 0 && funcs->control(tvh->priv, TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE) { int audio_format; char buf[128]; /* 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_tmsg(MSGT_TV, MSGL_ERR, "Audio type '%s (%x)' unsupported!\n", af_fmt2str(audio_format, buf, 128), 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); funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLESIZE, &sh_audio->samplesize); 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_audio->gsh->codec = "mp-pcm"; sh_audio->format = audio_format; sh_audio->i_bps = sh_audio->samplerate * sh_audio->samplesize * sh_audio->channels.num; // emulate WF for win32 codecs: sh_audio->wf = malloc(sizeof(*sh_audio->wf)); sh_audio->wf->wFormatTag = sh_audio->format; sh_audio->wf->nChannels = sh_audio->channels.num; sh_audio->wf->wBitsPerSample = sh_audio->samplesize * 8; sh_audio->wf->nSamplesPerSec = sh_audio->samplerate; sh_audio->wf->nBlockAlign = sh_audio->samplesize * sh_audio->channels.num; sh_audio->wf->nAvgBytesPerSec = sh_audio->i_bps; mp_tmsg(MSGT_DECVIDEO, MSGL_V, " 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_msg(MSGT_TV,MSGL_WARN,"Unable to set gain control!\n"); return 0; }
// Initialization and runtime control static int control(struct af_instance* af, int cmd, void* arg) { switch(cmd){ case AF_CONTROL_REINIT:{ char buf1[256]; char buf2[256]; struct mp_audio *data = arg; int supported_ac3 = 0; // Make sure this filter isn't redundant if(af->data->format == data->format) return AF_DETACH; // A bit complex because we can convert AC3 // to generic iec61937 but not the other way // round. if (AF_FORMAT_IS_AC3(af->data->format)) supported_ac3 = AF_FORMAT_IS_AC3(data->format); else if (AF_FORMAT_IS_IEC61937(af->data->format)) supported_ac3 = AF_FORMAT_IS_IEC61937(data->format); // Allow trivial AC3-endianness conversion if (!supported_ac3) // Check for errors in configuration if((AF_OK != check_bps(data->bps)) || (AF_OK != check_format(data->format)) || (AF_OK != check_bps(af->data->bps)) || (AF_OK != check_format(af->data->format))) return AF_ERROR; af_fmt2str(data->format,buf1,256); af_fmt2str(af->data->format,buf2,256); mp_msg(MSGT_AFILTER, MSGL_V, "[format] Changing sample format from %s to %s\n", buf1, buf2); af->data->rate = data->rate; mp_audio_set_channels(af->data, &data->channels); af->mul = (double)af->data->bps / data->bps; af->play = play; // set default // look whether only endianness differences are there if ((af->data->format & ~AF_FORMAT_END_MASK) == (data->format & ~AF_FORMAT_END_MASK)) { mp_msg(MSGT_AFILTER, MSGL_V, "[format] Accelerated endianness conversion only\n"); af->play = play_swapendian; } if ((data->format == AF_FORMAT_FLOAT_NE) && (af->data->format == AF_FORMAT_S16_NE)) { mp_msg(MSGT_AFILTER, MSGL_V, "[format] Accelerated %s to %s conversion\n", buf1, buf2); af->play = play_float_s16; } if ((data->format == AF_FORMAT_S16_NE) && (af->data->format == AF_FORMAT_FLOAT_NE)) { mp_msg(MSGT_AFILTER, MSGL_V, "[format] Accelerated %s to %s conversion\n", buf1, buf2); af->play = play_s16_float; } return AF_OK; } case AF_CONTROL_COMMAND_LINE:{ int format = af_str2fmt_short(bstr0(arg)); if (!format) { mp_msg(MSGT_AFILTER, MSGL_ERR, "[format] %s is not a valid format\n", (char *)arg); return AF_ERROR; } if(AF_OK != af->control(af, AF_CONTROL_FORMAT_FMT | AF_CONTROL_SET,&format)) return AF_ERROR; return AF_OK; } case AF_CONTROL_FORMAT_FMT | AF_CONTROL_SET:{ // Check for errors in configuration if(!AF_FORMAT_IS_AC3(*(int*)arg) && AF_OK != check_format(*(int*)arg)) return AF_ERROR; mp_audio_set_format(af->data, *(int*)arg); return AF_OK; } } return AF_UNKNOWN; }
// open & setup audio device // return: 1=success 0=fail static int init(int rate,int channels,int format,int flags){ audio_info_t info; int pass; int ok; int convert_u8_s8; setup_device_paths(); if (enable_sample_timing == RTSC_UNKNOWN && !getenv("AO_SUN_DISABLE_SAMPLE_TIMING")) { enable_sample_timing = realtime_samplecounter_available(audio_dev); } mp_msg(MSGT_AO,MSGL_STATUS,"ao2: %d Hz %d chans %s [0x%X]\n", rate,channels,af_fmt2str_short(format),format); audio_fd=open(audio_dev, O_WRONLY); if(audio_fd<0){ mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_SUN_CantOpenAudioDev, audio_dev, strerror(errno)); return 0; } if (af2sunfmt(format) == AUDIO_ENCODING_NONE) format = AF_FORMAT_S16_NE; for (ok = pass = 0; pass <= 5; pass++) { /* pass 6&7 not useful */ AUDIO_INITINFO(&info); info.play.encoding = af2sunfmt(ao_data.format = format); info.play.precision = (format==AF_FORMAT_S16_NE ? AUDIO_PRECISION_16 : AUDIO_PRECISION_8); info.play.channels = ao_data.channels = channels; info.play.sample_rate = ao_data.samplerate = rate; convert_u8_s8 = 0; if (pass & 1) { /* * on some sun audio drivers, 8-bit unsigned LINEAR8 encoding is * not supported, but 8-bit signed encoding is. * * Try S8, and if it works, use our own U8->S8 conversion before * sending the samples to the sound driver. */ #ifdef AUDIO_ENCODING_LINEAR8 if (info.play.encoding != AUDIO_ENCODING_LINEAR8) #endif continue; info.play.encoding = AUDIO_ENCODING_LINEAR; convert_u8_s8 = 1; } if (pass & 2) { /* * on some sun audio drivers, only certain fixed sample rates are * supported. * * In case the requested sample rate is very close to one of the * supported rates, use the fixed supported rate instead. */ if (!(info.play.sample_rate = find_close_samplerate_match(audio_fd, rate))) continue; /* * I'm not returning the correct sample rate in * |ao_data.samplerate|, to avoid software resampling. * * ao_data.samplerate = info.play.sample_rate; */ } if (pass & 4) { /* like "pass & 2", but use the highest supported sample rate */ if (!(info.play.sample_rate = ao_data.samplerate = find_highest_samplerate(audio_fd))) continue; } ok = ioctl(audio_fd, AUDIO_SETINFO, &info) >= 0; if (ok) { /* audio format accepted by audio driver */ break; } /* * format not supported? * retry with different encoding and/or sample rate */ } if (!ok) { char buf[128]; mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_SUN_UnsupSampleRate, channels, af_fmt2str(format, buf, 128), rate); return 0; } if (convert_u8_s8) ao_data.format = AF_FORMAT_S8; bytes_per_sample = channels * info.play.precision / 8; ao_data.bps = byte_per_sec = bytes_per_sample * ao_data.samplerate; ao_data.outburst = byte_per_sec > 100000 ? 16384 : 8192; reset(); return 1; }