static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; AVFilterLink *inlink = ctx->inputs[0]; ResampleContext *s = ctx->priv; char buf1[64], buf2[64]; int ret; int64_t resampling_forced; if (s->avr) { avresample_close(s->avr); avresample_free(&s->avr); } if (inlink->channel_layout == outlink->channel_layout && inlink->sample_rate == outlink->sample_rate && (inlink->format == outlink->format || (av_get_channel_layout_nb_channels(inlink->channel_layout) == 1 && av_get_channel_layout_nb_channels(outlink->channel_layout) == 1 && av_get_planar_sample_fmt(inlink->format) == av_get_planar_sample_fmt(outlink->format)))) return 0; if (!(s->avr = avresample_alloc_context())) return AVERROR(ENOMEM); if (s->options) { int ret; AVDictionaryEntry *e = NULL; while ((e = av_dict_get(s->options, "", e, AV_DICT_IGNORE_SUFFIX))) av_log(ctx, AV_LOG_VERBOSE, "lavr option: %s=%s\n", e->key, e->value); ret = av_opt_set_dict(s->avr, &s->options); if (ret < 0) return ret; } av_opt_set_int(s->avr, "in_channel_layout", inlink ->channel_layout, 0); av_opt_set_int(s->avr, "out_channel_layout", outlink->channel_layout, 0); av_opt_set_int(s->avr, "in_sample_fmt", inlink ->format, 0); av_opt_set_int(s->avr, "out_sample_fmt", outlink->format, 0); av_opt_set_int(s->avr, "in_sample_rate", inlink ->sample_rate, 0); av_opt_set_int(s->avr, "out_sample_rate", outlink->sample_rate, 0); if ((ret = avresample_open(s->avr)) < 0) return ret; av_opt_get_int(s->avr, "force_resampling", 0, &resampling_forced); s->resampling = resampling_forced || (inlink->sample_rate != outlink->sample_rate); if (s->resampling) { outlink->time_base = (AVRational){ 1, outlink->sample_rate }; s->next_pts = AV_NOPTS_VALUE; s->next_in_pts = AV_NOPTS_VALUE; } else outlink->time_base = inlink->time_base; av_get_channel_layout_string(buf1, sizeof(buf1), -1, inlink ->channel_layout); av_get_channel_layout_string(buf2, sizeof(buf2), -1, outlink->channel_layout); av_log(ctx, AV_LOG_VERBOSE, "fmt:%s srate:%d cl:%s -> fmt:%s srate:%d cl:%s\n", av_get_sample_fmt_name(inlink ->format), inlink ->sample_rate, buf1, av_get_sample_fmt_name(outlink->format), outlink->sample_rate, buf2); return 0; }
void as_setup_audio_rendering ( lw_audio_output_handler_t *aohp, AVCodecContext *ctx, VideoInfo *vi, IScriptEnvironment *env, const char *filter_name, uint64_t channel_layout, int sample_rate ) { /* Channel layout. */ if( ctx->channel_layout == 0 ) ctx->channel_layout = av_get_default_channel_layout( ctx->channels ); if( channel_layout != 0 ) aohp->output_channel_layout = channel_layout; /* Sample rate. */ if( sample_rate > 0 ) aohp->output_sample_rate = sample_rate; /* Decide output Bits Per Sample. */ aohp->output_sample_format = as_decide_audio_output_sample_format( aohp->output_sample_format ); if( aohp->output_sample_format == AV_SAMPLE_FMT_S32 && (aohp->output_bits_per_sample == 0 || aohp->output_bits_per_sample == 24) ) { /* 24bit signed integer output */ aohp->s24_output = 1; aohp->output_bits_per_sample = 24; } else aohp->output_bits_per_sample = av_get_bytes_per_sample( aohp->output_sample_format ) * 8; /* Set up the number of planes and the block alignment of decoded and output data. */ int input_channels = av_get_channel_layout_nb_channels( ctx->channel_layout ); if( av_sample_fmt_is_planar( ctx->sample_fmt ) ) { aohp->input_planes = input_channels; aohp->input_block_align = av_get_bytes_per_sample( ctx->sample_fmt ); } else { aohp->input_planes = 1; aohp->input_block_align = av_get_bytes_per_sample( ctx->sample_fmt ) * input_channels; } int output_channels = av_get_channel_layout_nb_channels( aohp->output_channel_layout ); aohp->output_block_align = (output_channels * aohp->output_bits_per_sample) / 8; /* Set up resampler. */ AVAudioResampleContext *avr_ctx = aohp->avr_ctx; avr_ctx = avresample_alloc_context(); if( !avr_ctx ) env->ThrowError( "%s: failed to avresample_alloc_context.", filter_name ); aohp->avr_ctx = avr_ctx; av_opt_set_int( avr_ctx, "in_channel_layout", ctx->channel_layout, 0 ); av_opt_set_int( avr_ctx, "in_sample_fmt", ctx->sample_fmt, 0 ); av_opt_set_int( avr_ctx, "in_sample_rate", ctx->sample_rate, 0 ); av_opt_set_int( avr_ctx, "out_channel_layout", aohp->output_channel_layout, 0 ); av_opt_set_int( avr_ctx, "out_sample_fmt", aohp->output_sample_format, 0 ); av_opt_set_int( avr_ctx, "out_sample_rate", aohp->output_sample_rate, 0 ); av_opt_set_int( avr_ctx, "internal_sample_fmt", AV_SAMPLE_FMT_FLTP, 0 ); if( avresample_open( avr_ctx ) < 0 ) env->ThrowError( "%s: failed to open resampler.", filter_name ); /* Set up AviSynth output format. */ vi->nchannels = output_channels; vi->audio_samples_per_second = aohp->output_sample_rate; switch ( aohp->output_sample_format ) { case AV_SAMPLE_FMT_U8 : case AV_SAMPLE_FMT_U8P : vi->sample_type = SAMPLE_INT8; break; case AV_SAMPLE_FMT_S16 : case AV_SAMPLE_FMT_S16P : vi->sample_type = SAMPLE_INT16; break; case AV_SAMPLE_FMT_S32 : case AV_SAMPLE_FMT_S32P : vi->sample_type = aohp->s24_output ? SAMPLE_INT24 : SAMPLE_INT32; break; case AV_SAMPLE_FMT_FLT : case AV_SAMPLE_FMT_FLTP : vi->sample_type = SAMPLE_FLOAT; break; default : env->ThrowError( "%s: %s is not supported.", filter_name, av_get_sample_fmt_name( ctx->sample_fmt ) ); } }
void CMixer::Init(AVSampleFormat in_avsf, DWORD in_layout, DWORD out_layout, int in_samplerate, int out_samplerate) { // reset parameters m_in_avsf = AV_SAMPLE_FMT_NONE; m_in_layout = 0; m_out_layout = 0; m_in_samplerate = 0; m_out_samplerate = 0; av_free(m_matrix_dbl); // Close Resample Context avresample_close(m_pAVRCxt); if (in_avsf >= AV_SAMPLE_FMT_U8P && in_avsf <= AV_SAMPLE_FMT_DBLP) { // planar audio is not supported (ffmpeg crashed) m_in_avsf_used = AV_SAMPLE_FMT_FLT; // convert to float } else { m_in_avsf_used = in_avsf; } int ret = 0; // Set options av_opt_set_int(m_pAVRCxt, "in_sample_fmt", m_in_avsf_used, 0); av_opt_set_int(m_pAVRCxt, "out_sample_fmt", AV_SAMPLE_FMT_FLT, 0); // forced float output av_opt_set_int(m_pAVRCxt, "in_channel_layout", in_layout, 0); av_opt_set_int(m_pAVRCxt, "out_channel_layout", out_layout, 0); av_opt_set_int(m_pAVRCxt, "in_sample_rate", in_samplerate, 0); av_opt_set_int(m_pAVRCxt, "out_sample_rate", out_samplerate, 0); // Open Resample Context ret = avresample_open(m_pAVRCxt); if (ret < 0) { TRACE(_T("Mixer: avresample_open failed\n")); return; } // Create Matrix int in_ch = av_popcount(in_layout); int out_ch = av_popcount(out_layout); m_matrix_dbl = (double*)av_mallocz(in_ch * out_ch * sizeof(*m_matrix_dbl)); // expand stereo if (in_layout == AV_CH_LAYOUT_STEREO && (out_layout == AV_CH_LAYOUT_QUAD || out_layout == AV_CH_LAYOUT_5POINT1 || out_layout == AV_CH_LAYOUT_7POINT1)) { m_matrix_dbl[0] = 1.0; m_matrix_dbl[1] = 0.0; m_matrix_dbl[2] = 0.0; m_matrix_dbl[3] = 1.0; if (out_layout == AV_CH_LAYOUT_QUAD) { m_matrix_dbl[4] = 0.6666; m_matrix_dbl[5] = (-0.2222); m_matrix_dbl[6] = (-0.2222); m_matrix_dbl[7] = 0.6666; } else if (out_layout == AV_CH_LAYOUT_5POINT1 || out_layout == AV_CH_LAYOUT_7POINT1) { m_matrix_dbl[4] = 0.5; m_matrix_dbl[5] = 0.5; m_matrix_dbl[6] = 0.0; m_matrix_dbl[7] = 0.0; m_matrix_dbl[8] = 0.6666; m_matrix_dbl[9] = (-0.2222); m_matrix_dbl[10] = (-0.2222); m_matrix_dbl[11] = 0.6666; if (out_layout == AV_CH_LAYOUT_7POINT1) { m_matrix_dbl[12] = 0.6666; m_matrix_dbl[13] = (-0.2222); m_matrix_dbl[14] = (-0.2222); m_matrix_dbl[15] = 0.6666; } } } else { const double center_mix_level = M_SQRT1_2; const double surround_mix_level = M_SQRT1_2; const double lfe_mix_level = M_SQRT1_2; const int normalize = 0; ret = avresample_build_matrix(in_layout, out_layout, center_mix_level, surround_mix_level, lfe_mix_level, normalize, m_matrix_dbl, in_ch, AV_MATRIX_ENCODING_NONE); if (ret < 0) { TRACE(_T("Mixer: avresample_build_matrix failed\n")); av_free(m_matrix_dbl); return; } } #ifdef _DEBUG CString matrix_str; for (int j = 0; j < out_ch; j++) { matrix_str.AppendFormat(_T("%d:"), j + 1); for (int i = 0; i < in_ch; i++) { double k = m_matrix_dbl[j * in_ch + i]; matrix_str.AppendFormat(_T(" %.4f"), k); } matrix_str += _T("\n"); } TRACE(matrix_str); #endif // Set Matrix on the context ret = avresample_set_matrix(m_pAVRCxt, m_matrix_dbl, in_ch); if (ret < 0) { TRACE(_T("Mixer: avresample_set_matrix failed\n")); av_free(m_matrix_dbl); return; } m_in_avsf = in_avsf; m_in_layout = in_layout; m_out_layout = out_layout; m_in_samplerate = in_samplerate; m_out_samplerate = out_samplerate; }
int decoder_init(PlayerCtx *ctx, const char *file) { int i; memset(ctx, 0, sizeof(*ctx)); ctx->video_idx = -1; ctx->audio_idx = -1; ctx->cur_seekid = 1; ctx->a_cur_pts = 0; AVInputFormat *format = NULL; if (!strncmp(file, "x11grab://", 10)) { printf("Using X11Grab\n"); format = av_find_input_format("x11grab"); file += 10; } if (avformat_open_input(&ctx->fmt_ctx, file, format, NULL) != 0) { printf("Couldn't open input file %s\n", file); return -1; } if (avformat_find_stream_info(ctx->fmt_ctx, NULL) < 0) { printf("Couldn't get stream info\n"); return -1; } ctx->duration = ctx->fmt_ctx->duration/(double)AV_TIME_BASE; pthread_mutex_init(&ctx->seek_mutex, NULL); pthread_cond_init(&ctx->seek_cond, NULL); for (i = 0; i < ctx->fmt_ctx->nb_streams; i++) { switch (ctx->fmt_ctx->streams[i]->codec->codec_type) { case AVMEDIA_TYPE_VIDEO: if (ctx->video_idx == -1) ctx->video_idx = i; break; case AVMEDIA_TYPE_AUDIO: if (ctx->audio_idx == -1) ctx->audio_idx = i; break; default: break; } } if (ctx->video_idx == -1) { printf("No video streams\n"); return -1; } if (ctx->audio_idx != -1) { ctx->a_stream = ctx->fmt_ctx->streams[ctx->audio_idx]; ctx->a_codec_ctx = ctx->a_stream->codec; ctx->a_codec = avcodec_find_decoder(ctx->a_codec_ctx->codec_id); if (ctx->a_codec == NULL) { printf("No audio codec\n"); return -1; } if (avcodec_open2(ctx->a_codec_ctx, ctx->a_codec, NULL) < 0) { printf("Failed to open audio codec\n"); return -1; } printf("Audio srate: %d\n", ctx->a_codec_ctx->sample_rate); ctx->a_resampler = avresample_alloc_context(); av_opt_set_int(ctx->a_resampler, "in_channel_layout", ctx->a_codec_ctx->channel_layout, 0); av_opt_set_int(ctx->a_resampler, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); av_opt_set_int(ctx->a_resampler, "in_sample_rate", ctx->a_codec_ctx->sample_rate, 0); av_opt_set_int(ctx->a_resampler, "out_sample_rate", SAMPLE_RATE, 0); av_opt_set_int(ctx->a_resampler, "in_sample_fmt", ctx->a_codec_ctx->sample_fmt, 0); av_opt_set_int(ctx->a_resampler, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); if (avresample_open(ctx->a_resampler)) return -1; ctx->a_ratio = SAMPLE_RATE/(double)ctx->a_codec_ctx->sample_rate; ctx->a_resample_output[0] = malloc(2 * sizeof(short) * AVCODEC_MAX_AUDIO_FRAME_SIZE * (ctx->a_ratio * 1.1)); ctx->a_resample_output[1] = 0; ctx->a_buf_len = AUDIO_BUF*SAMPLE_RATE; ctx->a_buf = malloc(sizeof(*ctx->a_buf) * ctx->a_buf_len); ctx->a_buf_put = 0; ctx->a_buf_get = 0; pthread_mutex_init(&ctx->a_buf_mutex, NULL); pthread_cond_init(&ctx->a_buf_not_full, NULL); pthread_cond_init(&ctx->a_buf_not_empty, NULL); } ctx->v_stream = ctx->fmt_ctx->streams[ctx->video_idx]; ctx->v_codec_ctx = ctx->v_stream->codec; ctx->width = ctx->v_codec_ctx->width; ctx->height = ctx->v_codec_ctx->height; ctx->v_codec = avcodec_find_decoder(ctx->v_codec_ctx->codec_id); if (ctx->v_codec == NULL) { printf("No video codec\n"); return -1; } if (avcodec_open2(ctx->v_codec_ctx, ctx->v_codec, NULL) < 0) { printf("Failed to open video codec\n"); return -1; } ctx->v_pkt_pts = AV_NOPTS_VALUE; ctx->v_faulty_pts = ctx->v_faulty_dts = 0; ctx->v_last_pts = ctx->v_last_dts = INT64_MIN; ctx->v_buf_len = VIDEO_BUF; pthread_mutex_init(&ctx->v_buf_mutex, NULL); pthread_cond_init(&ctx->v_buf_not_full, NULL); pthread_cond_init(&ctx->v_buf_not_empty, NULL); if (pthread_create(&ctx->decoder_thread, NULL, decoder_thread, ctx) != 0) return -1; return 0; }
static int configure_lavrr(struct af_instance *af, struct mp_audio *in, struct mp_audio *out) { struct af_resample *s = af->priv; s->avrctx_ok = false; enum AVSampleFormat in_samplefmt = af_to_avformat(in->format); enum AVSampleFormat out_samplefmt = check_output_conversion(out->format); enum AVSampleFormat out_samplefmtp = av_get_planar_sample_fmt(out_samplefmt); if (in_samplefmt == AV_SAMPLE_FMT_NONE || out_samplefmt == AV_SAMPLE_FMT_NONE || out_samplefmtp == AV_SAMPLE_FMT_NONE) return AF_ERROR; avresample_close(s->avrctx); avresample_close(s->avrctx_out); s->ctx.out_rate = out->rate; s->ctx.in_rate_af = in->rate; s->ctx.in_rate = rate_from_speed(in->rate, s->playback_speed); s->ctx.out_format = out->format; s->ctx.in_format = in->format; s->ctx.out_channels= out->channels; s->ctx.in_channels = in->channels; s->ctx.filter_size = s->opts.filter_size; s->ctx.phase_shift = s->opts.phase_shift; s->ctx.linear = s->opts.linear; s->ctx.cutoff = s->opts.cutoff; av_opt_set_int(s->avrctx, "filter_size", s->ctx.filter_size, 0); av_opt_set_int(s->avrctx, "phase_shift", s->ctx.phase_shift, 0); av_opt_set_int(s->avrctx, "linear_interp", s->ctx.linear, 0); av_opt_set_double(s->avrctx, "cutoff", s->ctx.cutoff, 0); #if HAVE_LIBSWRESAMPLE av_opt_set_double(s->avrctx, "rematrix_maxval", 1.0, 0); #endif if (mp_set_avopts(af->log, s->avrctx, s->avopts) < 0) return AF_ERROR; struct mp_chmap map_in = in->channels; struct mp_chmap map_out = out->channels; // Try not to do any remixing if at least one is "unknown". if (mp_chmap_is_unknown(&map_in) || mp_chmap_is_unknown(&map_out)) { mp_chmap_set_unknown(&map_in, map_in.num); mp_chmap_set_unknown(&map_out, map_out.num); } // unchecked: don't take any channel reordering into account uint64_t in_ch_layout = mp_chmap_to_lavc_unchecked(&map_in); uint64_t out_ch_layout = mp_chmap_to_lavc_unchecked(&map_out); struct mp_chmap in_lavc; mp_chmap_from_lavc(&in_lavc, in_ch_layout); if (in_lavc.num != map_in.num) { // For handling NA channels, we would have to add a planarization step. MP_FATAL(af, "Unsupported channel remapping.\n"); return AF_ERROR; } mp_chmap_get_reorder(s->reorder_in, &map_in, &in_lavc); transpose_order(s->reorder_in, map_in.num); struct mp_chmap out_lavc; mp_chmap_from_lavc(&out_lavc, out_ch_layout); if (mp_chmap_equals(&out_lavc, &map_out)) { // No intermediate step required - output new format directly. out_samplefmtp = out_samplefmt; } else { // Verify that we really just reorder and/or insert NA channels. struct mp_chmap withna = out_lavc; mp_chmap_fill_na(&withna, map_out.num); if (withna.num != map_out.num) return AF_ERROR; } mp_chmap_get_reorder(s->reorder_out, &out_lavc, &map_out); s->avrctx_fmt = *out; mp_audio_set_channels(&s->avrctx_fmt, &out_lavc); mp_audio_set_format(&s->avrctx_fmt, af_from_avformat(out_samplefmtp)); s->pre_out_fmt = *out; mp_audio_set_format(&s->pre_out_fmt, af_from_avformat(out_samplefmt)); // If there are NA channels, the final output will have more channels than // the avrctx output. Also, avrctx will output planar (out_samplefmtp was // not overwritten). Allocate the output frame with more channels, so the // NA channels can be trivially added. s->pool_fmt = s->avrctx_fmt; if (map_out.num > out_lavc.num) mp_audio_set_channels(&s->pool_fmt, &map_out); // Real conversion; output is input to avrctx_out. av_opt_set_int(s->avrctx, "in_channel_layout", in_ch_layout, 0); av_opt_set_int(s->avrctx, "out_channel_layout", out_ch_layout, 0); av_opt_set_int(s->avrctx, "in_sample_rate", s->ctx.in_rate, 0); av_opt_set_int(s->avrctx, "out_sample_rate", s->ctx.out_rate, 0); av_opt_set_int(s->avrctx, "in_sample_fmt", in_samplefmt, 0); av_opt_set_int(s->avrctx, "out_sample_fmt", out_samplefmtp, 0); // Just needs the correct number of channels. int fake_out_ch_layout = av_get_default_channel_layout(map_out.num); if (!fake_out_ch_layout) return AF_ERROR; // Deplanarize if needed. av_opt_set_int(s->avrctx_out, "in_channel_layout", fake_out_ch_layout, 0); av_opt_set_int(s->avrctx_out, "out_channel_layout", fake_out_ch_layout, 0); av_opt_set_int(s->avrctx_out, "in_sample_fmt", out_samplefmtp, 0); av_opt_set_int(s->avrctx_out, "out_sample_fmt", out_samplefmt, 0); av_opt_set_int(s->avrctx_out, "in_sample_rate", s->ctx.out_rate, 0); av_opt_set_int(s->avrctx_out, "out_sample_rate", s->ctx.out_rate, 0); // API has weird requirements, quoting avresample.h: // * This function can only be called when the allocated context is not open. // * Also, the input channel layout must have already been set. avresample_set_channel_mapping(s->avrctx, s->reorder_in); if (avresample_open(s->avrctx) < 0 || avresample_open(s->avrctx_out) < 0) { MP_ERR(af, "Cannot open Libavresample Context. \n"); return AF_ERROR; } s->avrctx_ok = true; return AF_OK; }
static int open_card( decklink_opts_t *decklink_opts ) { decklink_ctx_t *decklink_ctx = &decklink_opts->decklink_ctx; int found_mode; int ret = 0; int i; int cpu_flags; const int sample_rate = 48000; const char *model_name; BMDDisplayMode wanted_mode_id; IDeckLinkDisplayModeIterator *p_display_iterator = NULL; IDeckLinkIterator *decklink_iterator = NULL; HRESULT result; avcodec_register_all(); decklink_ctx->dec = avcodec_find_decoder( AV_CODEC_ID_V210 ); if( !decklink_ctx->dec ) { fprintf( stderr, "[decklink] Could not find v210 decoder\n" ); goto finish; } decklink_ctx->codec = avcodec_alloc_context3( decklink_ctx->dec ); if( !decklink_ctx->codec ) { fprintf( stderr, "[decklink] Could not allocate AVCodecContext\n" ); goto finish; } decklink_ctx->codec->get_buffer = obe_get_buffer; decklink_ctx->codec->release_buffer = obe_release_buffer; decklink_ctx->codec->reget_buffer = obe_reget_buffer; decklink_ctx->codec->flags |= CODEC_FLAG_EMU_EDGE; /* TODO: setup custom strides */ if( avcodec_open2( decklink_ctx->codec, decklink_ctx->dec, NULL ) < 0 ) { fprintf( stderr, "[decklink] Could not open libavcodec\n" ); goto finish; } decklink_iterator = CreateDeckLinkIteratorInstance(); if( !decklink_iterator ) { fprintf( stderr, "[decklink] DeckLink drivers not found\n" ); ret = -1; goto finish; } if( decklink_opts->card_idx < 0 ) { fprintf( stderr, "[decklink] Invalid card index %d \n", decklink_opts->card_idx ); ret = -1; goto finish; } for( i = 0; i <= decklink_opts->card_idx; ++i ) { if( decklink_ctx->p_card ) decklink_ctx->p_card->Release(); result = decklink_iterator->Next( &decklink_ctx->p_card ); if( result != S_OK ) break; } if( result != S_OK ) { fprintf( stderr, "[decklink] DeckLink PCI card %d not found\n", decklink_opts->card_idx ); ret = -1; goto finish; } result = decklink_ctx->p_card->GetModelName( &model_name ); if( result != S_OK ) { fprintf( stderr, "[decklink] Could not get model name\n" ); ret = -1; goto finish; } syslog( LOG_INFO, "Opened DeckLink PCI card %d (%s)", decklink_opts->card_idx, model_name ); if( decklink_ctx->p_card->QueryInterface( IID_IDeckLinkInput, (void**)&decklink_ctx->p_input) != S_OK ) { fprintf( stderr, "[decklink] Card has no inputs\n" ); ret = -1; goto finish; } /* Set up the video and audio sources. */ if( decklink_ctx->p_card->QueryInterface( IID_IDeckLinkConfiguration, (void**)&decklink_ctx->p_config) != S_OK ) { fprintf( stderr, "[decklink] Failed to get configuration interface\n" ); ret = -1; goto finish; } /* Setup video connection */ for( i = 0; video_conn_tab[i].obe_name != -1; i++ ) { if( video_conn_tab[i].obe_name == decklink_opts->video_conn ) break; } if( video_conn_tab[i].obe_name == -1 ) { fprintf( stderr, "[decklink] Unsupported video input connection\n" ); ret = -1; goto finish; } result = decklink_ctx->p_config->SetInt( bmdDeckLinkConfigVideoInputConnection, video_conn_tab[i].bmd_name ); if( result != S_OK ) { fprintf( stderr, "[decklink] Failed to set video input connection\n" ); ret = -1; goto finish; } /* Setup audio connection */ for( i = 0; audio_conn_tab[i].obe_name != -1; i++ ) { if( audio_conn_tab[i].obe_name == decklink_opts->audio_conn ) break; } if( audio_conn_tab[i].obe_name == -1 ) { fprintf( stderr, "[decklink] Unsupported audio input connection\n" ); ret = -1; goto finish; } result = decklink_ctx->p_config->SetInt( bmdDeckLinkConfigAudioInputConnection, audio_conn_tab[i].bmd_name ); if( result != S_OK ) { fprintf( stderr, "[decklink] Failed to set audio input connection\n" ); ret = -1; goto finish; } /* Get the list of display modes. */ result = decklink_ctx->p_input->GetDisplayModeIterator( &p_display_iterator ); if( result != S_OK ) { fprintf( stderr, "[decklink] Failed to enumerate display modes\n" ); ret = -1; goto finish; } for( i = 0; video_format_tab[i].obe_name != -1; i++ ) { if( video_format_tab[i].obe_name == decklink_opts->video_format ) break; } if( video_format_tab[i].obe_name == -1 ) { fprintf( stderr, "[decklink] Unsupported video format\n" ); ret = -1; goto finish; } wanted_mode_id = video_format_tab[i].bmd_name; found_mode = false; decklink_opts->timebase_num = video_format_tab[i].timebase_num; decklink_opts->timebase_den = video_format_tab[i].timebase_den; for (;;) { IDeckLinkDisplayMode *p_display_mode; result = p_display_iterator->Next( &p_display_mode ); if( result != S_OK || !p_display_mode ) break; BMDDisplayMode mode_id = p_display_mode->GetDisplayMode(); BMDTimeValue frame_duration, time_scale; result = p_display_mode->GetFrameRate( &frame_duration, &time_scale ); if( result != S_OK ) { fprintf( stderr, "[decklink] Failed to get frame rate\n" ); ret = -1; p_display_mode->Release(); goto finish; } if( wanted_mode_id == mode_id ) { found_mode = true; decklink_opts->width = p_display_mode->GetWidth(); decklink_opts->coded_height = p_display_mode->GetHeight(); switch( p_display_mode->GetFieldDominance() ) { case bmdProgressiveFrame: decklink_opts->interlaced = 0; decklink_opts->tff = 0; break; case bmdProgressiveSegmentedFrame: /* Assume tff interlaced - this mode should not be used in broadcast */ decklink_opts->interlaced = 1; decklink_opts->tff = 1; break; case bmdUpperFieldFirst: decklink_opts->interlaced = 1; decklink_opts->tff = 1; break; case bmdLowerFieldFirst: decklink_opts->interlaced = 1; decklink_opts->tff = 0; break; case bmdUnknownFieldDominance: default: /* Assume progressive */ decklink_opts->interlaced = 0; decklink_opts->tff = 0; break; } } p_display_mode->Release(); } decklink_opts->height = decklink_opts->coded_height; if( decklink_opts->coded_height == 486 ) decklink_opts->height = 480; if( !found_mode ) { fprintf( stderr, "[decklink] Unsupported video mode\n" ); ret = -1; goto finish; } cpu_flags = av_get_cpu_flags(); /* Setup VBI and VANC unpack functions */ if( IS_SD( decklink_opts->video_format ) ) { decklink_ctx->unpack_line = obe_v210_line_to_uyvy_c; decklink_ctx->downscale_line = obe_downscale_line_c; decklink_ctx->blank_line = obe_blank_line_uyvy_c; if( cpu_flags & AV_CPU_FLAG_MMX ) decklink_ctx->downscale_line = obe_downscale_line_mmx; if( cpu_flags & AV_CPU_FLAG_SSE2 ) decklink_ctx->downscale_line = obe_downscale_line_sse2; } else { decklink_ctx->unpack_line = obe_v210_line_to_nv20_c; decklink_ctx->blank_line = obe_blank_line_nv20_c; } result = decklink_ctx->p_input->EnableVideoInput( wanted_mode_id, bmdFormat10BitYUV, 0 ); if( result != S_OK ) { fprintf( stderr, "[decklink] Failed to enable video input\n" ); ret = -1; goto finish; } /* Set up audio. */ result = decklink_ctx->p_input->EnableAudioInput( sample_rate, bmdAudioSampleType32bitInteger, decklink_opts->num_channels ); if( result != S_OK ) { fprintf( stderr, "[decklink] Failed to enable audio input\n" ); ret = -1; goto finish; } if( !decklink_opts->probe ) { decklink_ctx->avr = avresample_alloc_context(); if( !decklink_ctx->avr ) { fprintf( stderr, "[decklink-sdiaudio] couldn't setup sample rate conversion \n" ); ret = -1; goto finish; } /* Give libavresample a made up channel map */ av_opt_set_int( decklink_ctx->avr, "in_channel_layout", (1 << decklink_opts->num_channels) - 1, 0 ); av_opt_set_int( decklink_ctx->avr, "in_sample_fmt", AV_SAMPLE_FMT_S32, 0 ); av_opt_set_int( decklink_ctx->avr, "in_sample_rate", 48000, 0 ); av_opt_set_int( decklink_ctx->avr, "out_channel_layout", (1 << decklink_opts->num_channels) - 1, 0 ); av_opt_set_int( decklink_ctx->avr, "out_sample_fmt", AV_SAMPLE_FMT_S32P, 0 ); if( avresample_open( decklink_ctx->avr ) < 0 ) { fprintf( stderr, "Could not open AVResample\n" ); goto finish; } } decklink_ctx->p_delegate = new DeckLinkCaptureDelegate( decklink_opts ); decklink_ctx->p_input->SetCallback( decklink_ctx->p_delegate ); result = decklink_ctx->p_input->StartStreams(); if( result != S_OK ) { fprintf( stderr, "[decklink] Could not start streaming from card\n" ); ret = -1; goto finish; } ret = 0; finish: if( decklink_iterator ) decklink_iterator->Release(); if( p_display_iterator ) p_display_iterator->Release(); if( ret ) close_card( decklink_opts ); return ret; }
static void audio_process_audio(audio_decoder_t *ad, media_buf_t *mb) { const audio_class_t *ac = ad->ad_ac; AVFrame *frame = ad->ad_frame; media_pipe_t *mp = ad->ad_mp; media_queue_t *mq = &mp->mp_audio; int r; int got_frame; AVPacket avpkt; int offset = 0; if(mb->mb_skip || mb->mb_stream != mq->mq_stream) return; while(offset < mb->mb_size) { if(mb->mb_cw == NULL) { frame->sample_rate = mb->mb_rate; frame->format = AV_SAMPLE_FMT_S16; switch(mb->mb_channels) { case 1: frame->channel_layout = AV_CH_LAYOUT_MONO; frame->nb_samples = mb->mb_size / 2; break; case 2: frame->channel_layout = AV_CH_LAYOUT_STEREO; frame->nb_samples = mb->mb_size / 4; break; default: abort(); } frame->data[0] = mb->mb_data; frame->linesize[0] = 0; r = mb->mb_size; got_frame = 1; } else { media_codec_t *mc = mb->mb_cw; AVCodecContext *ctx = mc->ctx; if(mc->codec_id != ad->ad_in_codec_id) { AVCodec *codec = avcodec_find_decoder(mc->codec_id); TRACE(TRACE_DEBUG, "audio", "Codec changed to %s", codec ? codec->name : "???"); ad->ad_in_codec_id = mc->codec_id; audio_cleanup_spdif_muxer(ad); if(ac->ac_check_passthru != NULL && codec != NULL && ac->ac_check_passthru(ad, mc->codec_id)) { audio_setup_spdif_muxer(ad, codec, mq); } } av_init_packet(&avpkt); avpkt.data = mb->mb_data + offset; avpkt.size = mb->mb_size - offset; if(ad->ad_spdif_muxer != NULL) { av_write_frame(ad->ad_spdif_muxer, &avpkt); avio_flush(ad->ad_spdif_muxer->pb); ad->ad_pts = mb->mb_pts; ad->ad_epoch = mb->mb_epoch; return; } if(ctx == NULL) { AVCodec *codec = avcodec_find_decoder(mc->codec_id); assert(codec != NULL); // Checked in libav.c ctx = mc->ctx = avcodec_alloc_context3(codec); if(ad->ad_stereo_downmix) ctx->request_channels = 2; if(avcodec_open2(mc->ctx, codec, NULL) < 0) { av_freep(&mc->ctx); return; } } r = avcodec_decode_audio4(ctx, frame, &got_frame, &avpkt); if(r < 0) return; if(frame->sample_rate == 0) { frame->sample_rate = ctx->sample_rate; if(frame->sample_rate == 0 && mb->mb_cw->fmt_ctx) frame->sample_rate = mb->mb_cw->fmt_ctx->sample_rate; if(frame->sample_rate == 0) return; } if(frame->channel_layout == 0) { switch(ctx->channels) { case 1: frame->channel_layout = AV_CH_LAYOUT_MONO; break; case 2: frame->channel_layout = AV_CH_LAYOUT_STEREO; break; default: return; } } if(mp->mp_stats) mp_set_mq_meta(mq, ctx->codec, ctx); } if(offset == 0 && mb->mb_pts != AV_NOPTS_VALUE) { int od = 0, id = 0; if(ad->ad_avr != NULL) { od = avresample_available(ad->ad_avr) * 1000000LL / ad->ad_out_sample_rate; id = avresample_get_delay(ad->ad_avr) * 1000000LL / frame->sample_rate; } ad->ad_pts = mb->mb_pts - od - id; ad->ad_epoch = mb->mb_epoch; // printf("od=%-20d id=%-20d PTS=%-20ld oPTS=%-20ld\n", // od, id, mb->mb_pts, pts); if(mb->mb_drive_clock) mp_set_current_time(mp, mb->mb_pts - ad->ad_delay, mb->mb_epoch, mb->mb_delta); } offset += r; if(got_frame) { if(frame->sample_rate != ad->ad_in_sample_rate || frame->format != ad->ad_in_sample_format || frame->channel_layout != ad->ad_in_channel_layout) { ad->ad_in_sample_rate = frame->sample_rate; ad->ad_in_sample_format = frame->format; ad->ad_in_channel_layout = frame->channel_layout; ac->ac_reconfig(ad); if(ad->ad_avr == NULL) ad->ad_avr = avresample_alloc_context(); else avresample_close(ad->ad_avr); av_opt_set_int(ad->ad_avr, "in_sample_fmt", ad->ad_in_sample_format, 0); av_opt_set_int(ad->ad_avr, "in_sample_rate", ad->ad_in_sample_rate, 0); av_opt_set_int(ad->ad_avr, "in_channel_layout", ad->ad_in_channel_layout, 0); av_opt_set_int(ad->ad_avr, "out_sample_fmt", ad->ad_out_sample_format, 0); av_opt_set_int(ad->ad_avr, "out_sample_rate", ad->ad_out_sample_rate, 0); av_opt_set_int(ad->ad_avr, "out_channel_layout", ad->ad_out_channel_layout, 0); char buf1[128]; char buf2[128]; av_get_channel_layout_string(buf1, sizeof(buf1), -1, ad->ad_in_channel_layout); av_get_channel_layout_string(buf2, sizeof(buf2), -1, ad->ad_out_channel_layout); TRACE(TRACE_DEBUG, "Audio", "Converting from [%s %dHz %s] to [%s %dHz %s]", buf1, ad->ad_in_sample_rate, av_get_sample_fmt_name(ad->ad_in_sample_format), buf2, ad->ad_out_sample_rate, av_get_sample_fmt_name(ad->ad_out_sample_format)); if(avresample_open(ad->ad_avr)) { TRACE(TRACE_ERROR, "AudioQueue", "Unable to open resampler"); avresample_free(&ad->ad_avr); } if(ac->ac_set_volume != NULL) { prop_set(mp->mp_prop_ctrl, "canAdjustVolume", PROP_SET_INT, 1); ac->ac_set_volume(ad, ad->ad_vol_scale); } } if(ad->ad_avr != NULL) avresample_convert(ad->ad_avr, NULL, 0, 0, frame->data, frame->linesize[0], frame->nb_samples); } } }