static int encavcodecaInit(hb_work_object_t *w, hb_job_t *job) { AVCodec *codec; AVCodecContext *context; hb_audio_t *audio = w->audio; hb_work_private_t *pv = calloc(1, sizeof(hb_work_private_t)); w->private_data = pv; pv->job = job; pv->list = hb_list_init(); // channel count, layout and matrix encoding int matrix_encoding; uint64_t channel_layout = hb_ff_mixdown_xlat(audio->config.out.mixdown, &matrix_encoding); pv->out_discrete_channels = hb_mixdown_get_discrete_channel_count(audio->config.out.mixdown); // default settings and options AVDictionary *av_opts = NULL; const char *codec_name = NULL; enum AVCodecID codec_id = AV_CODEC_ID_NONE; enum AVSampleFormat sample_fmt = AV_SAMPLE_FMT_FLTP; int bits_per_raw_sample = 0; int profile = FF_PROFILE_UNKNOWN; // override with encoder-specific values switch (audio->config.out.codec) { case HB_ACODEC_AC3: codec_id = AV_CODEC_ID_AC3; if (matrix_encoding != AV_MATRIX_ENCODING_NONE) av_dict_set(&av_opts, "dsur_mode", "on", 0); break; case HB_ACODEC_FFEAC3: codec_id = AV_CODEC_ID_EAC3; if (matrix_encoding != AV_MATRIX_ENCODING_NONE) av_dict_set(&av_opts, "dsur_mode", "on", 0); break; case HB_ACODEC_FDK_AAC: case HB_ACODEC_FDK_HAAC: codec_name = "libfdk_aac"; sample_fmt = AV_SAMPLE_FMT_S16; bits_per_raw_sample = 16; switch (audio->config.out.codec) { case HB_ACODEC_FDK_HAAC: profile = FF_PROFILE_AAC_HE; break; default: profile = FF_PROFILE_AAC_LOW; break; } // Libav's libfdk-aac wrapper expects back channels for 5.1 // audio, and will error out unless we translate the layout if (channel_layout == AV_CH_LAYOUT_5POINT1) channel_layout = AV_CH_LAYOUT_5POINT1_BACK; break; case HB_ACODEC_FFAAC: codec_name = "aac"; av_dict_set(&av_opts, "stereo_mode", "ms_off", 0); break; case HB_ACODEC_FFFLAC: case HB_ACODEC_FFFLAC24: codec_id = AV_CODEC_ID_FLAC; switch (audio->config.out.codec) { case HB_ACODEC_FFFLAC24: sample_fmt = AV_SAMPLE_FMT_S32; bits_per_raw_sample = 24; break; default: sample_fmt = AV_SAMPLE_FMT_S16; bits_per_raw_sample = 16; break; } break; default: hb_error("encavcodecaInit: unsupported codec (0x%x)", audio->config.out.codec); return 1; } if (codec_name != NULL) { codec = avcodec_find_encoder_by_name(codec_name); if (codec == NULL) { hb_error("encavcodecaInit: avcodec_find_encoder_by_name(%s) failed", codec_name); return 1; } } else { codec = avcodec_find_encoder(codec_id); if (codec == NULL) { hb_error("encavcodecaInit: avcodec_find_encoder(%d) failed", codec_id); return 1; } } // allocate the context and apply the settings context = avcodec_alloc_context3(codec); hb_ff_set_sample_fmt(context, codec, sample_fmt); context->bits_per_raw_sample = bits_per_raw_sample; context->profile = profile; context->channel_layout = channel_layout; context->channels = pv->out_discrete_channels; context->sample_rate = audio->config.out.samplerate; if (audio->config.out.bitrate > 0) { context->bit_rate = audio->config.out.bitrate * 1000; } else if (audio->config.out.quality >= 0) { context->global_quality = audio->config.out.quality * FF_QP2LAMBDA; context->flags |= CODEC_FLAG_QSCALE; if (audio->config.out.codec == HB_ACODEC_FDK_AAC || audio->config.out.codec == HB_ACODEC_FDK_HAAC) { char vbr[2]; snprintf(vbr, 2, "%.1g", audio->config.out.quality); av_dict_set(&av_opts, "vbr", vbr, 0); } } if (audio->config.out.compression_level >= 0) { context->compression_level = audio->config.out.compression_level; } // For some codecs, libav requires the following flag to be set // so that it fills extradata with global header information. // If this flag is not set, it inserts the data into each // packet instead. context->flags |= CODEC_FLAG_GLOBAL_HEADER; if (hb_avcodec_open(context, codec, &av_opts, 0)) { hb_error("encavcodecaInit: hb_avcodec_open() failed"); return 1; } // avcodec_open populates the opts dictionary with the // things it didn't recognize. AVDictionaryEntry *t = NULL; while ((t = av_dict_get(av_opts, "", t, AV_DICT_IGNORE_SUFFIX))) { hb_log("encavcodecaInit: Unknown avcodec option %s", t->key); } av_dict_free(&av_opts); pv->context = context; audio->config.out.samples_per_frame = pv->samples_per_frame = context->frame_size; pv->input_samples = context->frame_size * context->channels; pv->input_buf = malloc(pv->input_samples * sizeof(float)); // Some encoders in libav (e.g. fdk-aac) fail if the output buffer // size is not some minumum value. 8K seems to be enough :( pv->max_output_bytes = MAX(FF_MIN_BUFFER_SIZE, (pv->input_samples * av_get_bytes_per_sample(context->sample_fmt))); // sample_fmt conversion if (context->sample_fmt != AV_SAMPLE_FMT_FLT) { pv->output_buf = malloc(pv->max_output_bytes); pv->avresample = avresample_alloc_context(); if (pv->avresample == NULL) { hb_error("encavcodecaInit: avresample_alloc_context() failed"); return 1; } av_opt_set_int(pv->avresample, "in_sample_fmt", AV_SAMPLE_FMT_FLT, 0); av_opt_set_int(pv->avresample, "out_sample_fmt", context->sample_fmt, 0); av_opt_set_int(pv->avresample, "in_channel_layout", context->channel_layout, 0); av_opt_set_int(pv->avresample, "out_channel_layout", context->channel_layout, 0); if (hb_audio_dither_is_supported(audio->config.out.codec)) { // dithering needs the sample rate av_opt_set_int(pv->avresample, "in_sample_rate", context->sample_rate, 0); av_opt_set_int(pv->avresample, "out_sample_rate", context->sample_rate, 0); av_opt_set_int(pv->avresample, "dither_method", audio->config.out.dither_method, 0); } if (avresample_open(pv->avresample)) { hb_error("encavcodecaInit: avresample_open() failed"); avresample_free(&pv->avresample); return 1; } } else { pv->avresample = NULL; pv->output_buf = pv->input_buf; } if (context->extradata != NULL) { memcpy(w->config->extradata.bytes, context->extradata, context->extradata_size); w->config->extradata.length = context->extradata_size; } audio->config.out.delay = av_rescale_q(context->delay, context->time_base, (AVRational){1, 90000}); return 0; }
int decode_thread(void *arg) { VideoState *is = (VideoState *)arg; AVFormatContext *pFormatCtx = NULL; AVPacket pkt1, *packet = &pkt1; AVDictionary *io_dict = NULL; AVIOInterruptCB callback; int video_index = -1; int audio_index = -1; int i; is->videoStream = -1; is->audioStream = -1; is->audio_need_resample = 0; global_video_state = is; // will interrupt blocking functions if we quit! callback.callback = decode_interrupt_cb; callback.opaque = is; if(avio_open2(&is->io_context, is->filename, 0, &callback, &io_dict)) { fprintf(stderr, "Unable to open I/O for %s\n", is->filename); return -1; } // Open video file if(avformat_open_input(&pFormatCtx, is->filename, NULL, NULL) != 0) { return -1; // Couldn't open file } is->pFormatCtx = pFormatCtx; // Retrieve stream information if(avformat_find_stream_info(pFormatCtx, NULL) < 0) { return -1; // Couldn't find stream information } // Dump information about file onto standard error av_dump_format(pFormatCtx, 0, is->filename, 0); // Find the first video stream for(i = 0; i < pFormatCtx->nb_streams; i++) { if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && video_index < 0) { video_index = i; } if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO && audio_index < 0) { audio_index = i; } } if(audio_index >= 0) { stream_component_open(is, audio_index); } if(video_index >= 0) { stream_component_open(is, video_index); } if(is->videoStream < 0 && is->audioStream < 0) { fprintf(stderr, "%s: could not open codecs\n", is->filename); goto fail; } #ifdef __RESAMPLER__ if( audio_index >= 0 && pFormatCtx->streams[audio_index]->codec->sample_fmt != AV_SAMPLE_FMT_S16) { is->audio_need_resample = 1; is->pResampledOut = NULL; is->pSwrCtx = NULL; printf("Configure resampler: "); #ifdef __LIBAVRESAMPLE__ printf("libAvResample\n"); is->pSwrCtx = avresample_alloc_context(); #endif #ifdef __LIBSWRESAMPLE__ printf("libSwResample\n"); is->pSwrCtx = swr_alloc(); #endif // Some MP3/WAV don't tell this so make assumtion that // They are stereo not 5.1 if (pFormatCtx->streams[audio_index]->codec->channel_layout == 0 && pFormatCtx->streams[audio_index]->codec->channels == 2) { pFormatCtx->streams[audio_index]->codec->channel_layout = AV_CH_LAYOUT_STEREO; } else if (pFormatCtx->streams[audio_index]->codec->channel_layout == 0 && pFormatCtx->streams[audio_index]->codec->channels == 1) { pFormatCtx->streams[audio_index]->codec->channel_layout = AV_CH_LAYOUT_MONO; } else if (pFormatCtx->streams[audio_index]->codec->channel_layout == 0 && pFormatCtx->streams[audio_index]->codec->channels == 0) { pFormatCtx->streams[audio_index]->codec->channel_layout = AV_CH_LAYOUT_STEREO; pFormatCtx->streams[audio_index]->codec->channels = 2; } av_opt_set_int(is->pSwrCtx, "in_channel_layout", pFormatCtx->streams[audio_index]->codec->channel_layout, 0); av_opt_set_int(is->pSwrCtx, "in_sample_fmt", pFormatCtx->streams[audio_index]->codec->sample_fmt, 0); av_opt_set_int(is->pSwrCtx, "in_sample_rate", pFormatCtx->streams[audio_index]->codec->sample_rate, 0); av_opt_set_int(is->pSwrCtx, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); av_opt_set_int(is->pSwrCtx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); av_opt_set_int(is->pSwrCtx, "out_sample_rate", 44100, 0); #ifdef __LIBAVRESAMPLE__ if (avresample_open(is->pSwrCtx) < 0) { #else if (swr_init(is->pSwrCtx) < 0) { #endif fprintf(stderr, " ERROR!! From Samplert: %d Hz Sample format: %s\n", pFormatCtx->streams[audio_index]->codec->sample_rate, av_get_sample_fmt_name(pFormatCtx->streams[audio_index]->codec->sample_fmt)); fprintf(stderr, " To 44100 Sample format: s16\n"); is->audio_need_resample = 0; is->pSwrCtx = NULL;; } } #endif // main decode loop for(;;) { if(is->quit) { break; } // seek stuff goes here if(is->audioq.size > MAX_AUDIOQ_SIZE || is->videoq.size > MAX_VIDEOQ_SIZE) { SDL_Delay(10); continue; } if(av_read_frame(is->pFormatCtx, packet) < 0) { if(is->pFormatCtx->pb->error == 0) { SDL_Delay(100); /* no error; wait for user input */ continue; } else { break; } } // Is this a packet from the video stream? if(packet->stream_index == is->videoStream) { packet_queue_put(&is->videoq, packet); } else if(packet->stream_index == is->audioStream) { packet_queue_put(&is->audioq, packet); } else { av_free_packet(packet); } } /* all done - wait for it */ while(!is->quit) { SDL_Delay(100); } fail: { SDL_Event event; event.type = FF_QUIT_EVENT; event.user.data1 = is; SDL_PushEvent(&event); } return 0; } const char g_szClassName[] = "myWindowClass"; // Step 4: the Window Procedure LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } sem_t mutex; HWND hwnd; static void * window_manager(void * data) { printf("Window manager has been started!\n"); WNDCLASSEX wc; MSG Msg; //Step 1: Registering the Window Class wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; //wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName = NULL; wc.lpszClassName = g_szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if(!RegisterClassEx(&wc)) { MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); return 0; } // Step 2: Creating the Window hwnd = CreateWindowEx( WS_EX_CLIENTEDGE, g_szClassName, "The title of my window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, NULL, NULL, NULL, NULL); sem_post(&mutex); if(hwnd == NULL) { MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); return 0; } else { printf("window hwnd = %d\n", hwnd); } ShowWindow(hwnd, TRUE); UpdateWindow(hwnd); // Step 3: The Message Loop while(GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam; }
static int configure_lavrr(struct af_instance *af, struct mp_audio *in, struct mp_audio *out) { struct af_resample *s = af->priv; close_lavrr(af); s->avrctx = avresample_alloc_context(); s->avrctx_out = avresample_alloc_context(); if (!s->avrctx || !s->avrctx_out) goto error; 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) goto error; 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) goto 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"); goto 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) goto 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) goto 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"); goto error; } return AF_OK; error: close_lavrr(af); return AF_ERROR; }
static av_cold int opus_decode_init(AVCodecContext *avctx) { OpusContext *c = avctx->priv_data; int ret, i, j; avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; avctx->sample_rate = 48000; c->fdsp = avpriv_float_dsp_alloc(0); if (!c->fdsp) return AVERROR(ENOMEM); /* find out the channel configuration */ ret = ff_opus_parse_extradata(avctx, c); if (ret < 0) return ret; /* allocate and init each independent decoder */ c->streams = av_mallocz_array(c->nb_streams, sizeof(*c->streams)); if (!c->streams) { c->nb_streams = 0; ret = AVERROR(ENOMEM); goto fail; } for (i = 0; i < c->nb_streams; i++) { OpusStreamContext *s = &c->streams[i]; uint64_t layout; s->output_channels = (i < c->nb_stereo_streams) ? 2 : 1; s->avctx = avctx; for (j = 0; j < s->output_channels; j++) { s->silk_output[j] = s->silk_buf[j]; s->celt_output[j] = s->celt_buf[j]; s->redundancy_output[j] = s->redundancy_buf[j]; } s->fdsp = c->fdsp; #if CONFIG_SWRESAMPLE s->swr =swr_alloc(); if (!s->swr) goto fail; layout = (s->output_channels == 1) ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO; av_opt_set_int(s->swr, "in_sample_fmt", avctx->sample_fmt, 0); av_opt_set_int(s->swr, "out_sample_fmt", avctx->sample_fmt, 0); av_opt_set_int(s->swr, "in_channel_layout", layout, 0); av_opt_set_int(s->swr, "out_channel_layout", layout, 0); av_opt_set_int(s->swr, "out_sample_rate", avctx->sample_rate, 0); av_opt_set_int(s->swr, "filter_size", 16, 0); #elif CONFIG_AVRESAMPLE s->avr = avresample_alloc_context(); if (!s->avr) goto fail; layout = (s->output_channels == 1) ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO; av_opt_set_int(s->avr, "in_sample_fmt", avctx->sample_fmt, 0); av_opt_set_int(s->avr, "out_sample_fmt", avctx->sample_fmt, 0); av_opt_set_int(s->avr, "in_channel_layout", layout, 0); av_opt_set_int(s->avr, "out_channel_layout", layout, 0); av_opt_set_int(s->avr, "out_sample_rate", avctx->sample_rate, 0); #endif ret = ff_silk_init(avctx, &s->silk, s->output_channels); if (ret < 0) goto fail; ret = ff_celt_init(avctx, &s->celt, s->output_channels); if (ret < 0) goto fail; s->celt_delay = av_audio_fifo_alloc(avctx->sample_fmt, s->output_channels, 1024); if (!s->celt_delay) { ret = AVERROR(ENOMEM); goto fail; } } return 0; fail: opus_decode_close(avctx); return ret; }
inline ResampleContext *resample_alloc() { return avresample_alloc_context(); }
int decode_thread(void *arg) { VideoState *is = (VideoState *)arg; AVFormatContext *pFormatCtx = NULL; AVPacket pkt1, *packet = &pkt1; AVDictionary *io_dict = NULL; AVIOInterruptCB callback; int video_index = -1; int audio_index = -1; int i; is->videoStream=-1; is->audioStream=-1; is->audio_need_resample = 0; global_video_state = is; // will interrupt blocking functions if we quit! callback.callback = decode_interrupt_cb; callback.opaque = is; if (avio_open2(&is->io_context, is->filename, 0, &callback, &io_dict)) { fprintf(stderr, "Unable to open I/O for %s\n", is->filename); return -1; } // Open video file if(avformat_open_input(&pFormatCtx, is->filename, NULL, NULL)!=0) return -1; // Couldn't open file is->pFormatCtx = pFormatCtx; // Retrieve stream information if(avformat_find_stream_info(pFormatCtx, NULL)<0) return -1; // Couldn't find stream information // Dump information about file onto standard error av_dump_format(pFormatCtx, 0, is->filename, 0); // Find the first video stream for(i=0; i<pFormatCtx->nb_streams; i++) { if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO && video_index < 0) { video_index=i; } else if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO && audio_index < 0) { audio_index=i; } } if(audio_index >= 0) { stream_component_open(is, audio_index); } if(video_index >= 0) { stream_component_open(is, video_index); } if(is->videoStream < 0 && is->audioStream < 0) { fprintf(stderr, "%s: could not open codecs\n", is->filename); goto fail; } #ifdef __RESAMPLER__ if( audio_index >= 0 && pFormatCtx->streams[audio_index]->codec->sample_fmt != AV_SAMPLE_FMT_S16) { is->audio_need_resample=1; is->pResampledOut=NULL; is->pSwrCtx = NULL; printf("Configure resampler: "); #ifdef __LIBAVRESAMPLE__ printf("libAvResample\n"); is->pSwrCtx = avresample_alloc_context(); #endif #ifdef __LIBSWRESAMPLE__ printf("libSwResample\n"); is->pSwrCtx = swr_alloc(); #endif // Some MP3/WAV don't tell this so make assumtion that // They are stereo not 5.1 if (pFormatCtx->streams[audio_index]->codec->channel_layout == 0 && pFormatCtx->streams[audio_index]->codec->channels == 2) { pFormatCtx->streams[audio_index]->codec->channel_layout = AV_CH_LAYOUT_STEREO; } else if (pFormatCtx->streams[audio_index]->codec->channel_layout == 0 && pFormatCtx->streams[audio_index]->codec->channels == 1) { pFormatCtx->streams[audio_index]->codec->channel_layout = AV_CH_LAYOUT_MONO; } else if (pFormatCtx->streams[audio_index]->codec->channel_layout == 0 && pFormatCtx->streams[audio_index]->codec->channels == 0) { pFormatCtx->streams[audio_index]->codec->channel_layout = AV_CH_LAYOUT_STEREO; pFormatCtx->streams[audio_index]->codec->channels = 2; } av_opt_set_int(is->pSwrCtx,"in_channel_layout", pFormatCtx->streams[audio_index]->codec->channel_layout, 0); av_opt_set_int(is->pSwrCtx,"in_sample_fmt", pFormatCtx->streams[audio_index]->codec->sample_fmt, 0); av_opt_set_int(is->pSwrCtx,"in_sample_rate", pFormatCtx->streams[audio_index]->codec->sample_rate, 0); av_opt_set_int(is->pSwrCtx,"out_channel_layout", AV_CH_LAYOUT_STEREO, 0); av_opt_set_int(is->pSwrCtx,"out_sample_fmt", AV_SAMPLE_FMT_S16, 0); av_opt_set_int(is->pSwrCtx,"out_sample_rate", 44100, 0); #ifdef __LIBAVRESAMPLE__ if (avresample_open(is->pSwrCtx) < 0) { #else if (swr_init(is->pSwrCtx) < 0) { #endif fprintf(stderr, " ERROR!! From Samplert: %d Hz Sample format: %s\n", pFormatCtx->streams[audio_index]->codec->sample_rate, av_get_sample_fmt_name(pFormatCtx->streams[audio_index]->codec->sample_fmt)); fprintf(stderr, " To 44100 Sample format: s16\n"); is->audio_need_resample=0; is->pSwrCtx = NULL;; } } #endif // main decode loop for(;;) { if(is->quit) { break; } // seek stuff goes here if(is->seek_req) { int stream_index= -1; int64_t seek_target = is->seek_pos; if (is->videoStream >= 0) stream_index = is->videoStream; else if(is->audioStream >= 0) stream_index = is->audioStream; if(stream_index>=0) { seek_target= av_rescale_q(seek_target, AV_TIME_BASE_Q, pFormatCtx->streams[stream_index]->time_base); } printf("Seek_target: %ld/%ld stream_index: %ld\n",is->seek_pos, seek_target, stream_index); if(av_seek_frame(is->pFormatCtx, stream_index, seek_target, is->seek_flags) < 0) { fprintf(stderr, "%s: error while seeking\n", is->pFormatCtx->filename); } else { if(is->audioStream >= 0) { packet_queue_flush(&is->audioq); packet_queue_put(&is->audioq, &flush_pkt); } if(is->videoStream >= 0) { packet_queue_flush(&is->videoq); packet_queue_put(&is->videoq, &flush_pkt); } } is->seek_req = 0; } if(is->audioq.size > MAX_AUDIOQ_SIZE || is->videoq.size > MAX_VIDEOQ_SIZE) { SDL_Delay(10); continue; } if(av_read_frame(is->pFormatCtx, packet) < 0) { if(is->pFormatCtx->pb->error == 0) { SDL_Delay(100); /* no error; wait for user input */ continue; } else { break; } } // Is this a packet from the video stream? if(packet->stream_index == is->videoStream) { packet_queue_put(&is->videoq, packet); } else if(packet->stream_index == is->audioStream) { packet_queue_put(&is->audioq, packet); } else { av_free_packet(packet); } } /* all done - wait for it */ while(!is->quit) { SDL_Delay(100); } fail: { SDL_Event event; event.type = FF_QUIT_EVENT; event.user.data1 = is; SDL_PushEvent(&event); } return 0; } void stream_seek(VideoState *is, int64_t pos, int rel) { if(!is->seek_req) { is->seek_pos = pos; is->seek_flags = rel < 0 ? AVSEEK_FLAG_BACKWARD : 0; is->seek_req = 1; } } int main(int argc, char *argv[]) { SDL_Event event; //double pts; VideoState *is; is = av_mallocz(sizeof(VideoState)); if(argc < 2) { fprintf(stderr, "Usage: test <file>\n"); exit(1); } // Register all formats and codecs av_register_all(); if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) { fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError()); exit(1); } // Make a screen to put our video #ifndef __DARWIN__ screen = SDL_SetVideoMode(640, 480, 0, 0); #else screen = SDL_SetVideoMode(640, 480, 24, 0); #endif if(!screen) { fprintf(stderr, "SDL: could not set video mode - exiting\n"); exit(1); } av_strlcpy(is->filename, argv[1], 1024); is->pictq_mutex = SDL_CreateMutex(); is->pictq_cond = SDL_CreateCond(); schedule_refresh(is, 40); is->av_sync_type = DEFAULT_AV_SYNC_TYPE; is->parse_tid = SDL_CreateThread(decode_thread, is); if(!is->parse_tid) { av_free(is); return -1; } av_init_packet(&flush_pkt); flush_pkt.data = (unsigned char *)"FLUSH"; for(;;) { double incr, pos; SDL_WaitEvent(&event); switch(event.type) { case SDL_KEYDOWN: switch(event.key.keysym.sym) { case SDLK_LEFT: incr = -10.0; goto do_seek; case SDLK_RIGHT: incr = 10.0; goto do_seek; case SDLK_UP: incr = 60.0; goto do_seek; case SDLK_DOWN: incr = -60.0; goto do_seek; do_seek: if(global_video_state) { pos = get_master_clock(global_video_state); pos += incr; stream_seek(global_video_state, (int64_t)(pos * AV_TIME_BASE), incr); } break; default: break; } break; case FF_QUIT_EVENT: case SDL_QUIT: is->quit = 1; /* * If the video has finished playing, then both the picture and * audio queues are waiting for more data. Make them stop * waiting and terminate normally. */ SDL_CondSignal(is->audioq.cond); SDL_CondSignal(is->videoq.cond); SDL_Quit(); exit(0); break; case FF_ALLOC_EVENT: alloc_picture(event.user.data1); break; case FF_REFRESH_EVENT: video_refresh_timer(event.user.data1); break; default: break; } } return 0; }
void CMixer::Init(DWORD out_layout, DWORD in_layout, enum AVSampleFormat in_sf) { avresample_free(&m_pAVRCxt); int ret = 0; // Allocate Resample Context and set options. m_pAVRCxt = avresample_alloc_context(); av_opt_set_int(m_pAVRCxt, "in_channel_layout", in_layout, 0); av_opt_set_int(m_pAVRCxt, "in_sample_fmt", in_sf, 0); av_opt_set_int(m_pAVRCxt, "out_channel_layout", out_layout, 0); av_opt_set_int(m_pAVRCxt, "out_sample_fmt", AV_SAMPLE_FMT_FLT, 0); // forced float output // Open Resample Context ret = avresample_open(m_pAVRCxt); if (ret < 0) { TRACE(_T("Mixer: avresample_open failed\n")); avresample_free(&m_pAVRCxt); return; } // Create Matrix int in_ch = av_popcount(in_layout); int out_ch = av_popcount(out_layout); double* matrix_dbl = (double*)av_mallocz(in_ch * out_ch * sizeof(*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)) { matrix_dbl[0] = 1.0; matrix_dbl[1] = 0.0; matrix_dbl[2] = 0.0; matrix_dbl[3] = 1.0; if (out_layout == AV_CH_LAYOUT_QUAD) { matrix_dbl[4] = 0.5; matrix_dbl[5] = (-0.5); matrix_dbl[6] = (-0.5); matrix_dbl[7] = 0.5; } else if (out_layout == AV_CH_LAYOUT_5POINT1 || out_layout == AV_CH_LAYOUT_7POINT1) { matrix_dbl[4] = 0.5; matrix_dbl[5] = 0.5; matrix_dbl[6] = 0.0; matrix_dbl[7] = 0.0; matrix_dbl[8] = 0.5; matrix_dbl[9] = (-0.5); matrix_dbl[10] = (-0.5); matrix_dbl[11] = 0.5; if (out_layout == AV_CH_LAYOUT_7POINT1) { matrix_dbl[12] = 0.5; matrix_dbl[13] = (-0.5); matrix_dbl[14] = (-0.5); matrix_dbl[15] = 0.5; } } } 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, matrix_dbl, in_ch, AV_MATRIX_ENCODING_NONE); if (ret < 0) { TRACE(_T("Mixer: avresample_build_matrix failed\n")); av_free(matrix_dbl); avresample_free(&m_pAVRCxt); 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 = 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, matrix_dbl, in_ch); av_free(matrix_dbl); if (ret < 0) { TRACE(_T("Mixer: avresample_set_matrix failed\n")); avresample_free(&m_pAVRCxt); return; } last_in_layout = in_layout; last_out_layout = out_layout; last_in_sf = in_sf; }
/* * add an audio output stream */ static void add_audio_stream(OutputStream *ost, AVFormatContext *oc, enum AVCodecID codec_id) { AVCodecContext *c; AVCodec *codec; int ret; /* find the audio encoder */ codec = avcodec_find_encoder(codec_id); if (!codec) { fprintf(stderr, "codec not found\n"); exit(1); } ost->st = avformat_new_stream(oc, NULL); if (!ost->st) { fprintf(stderr, "Could not alloc stream\n"); exit(1); } c = avcodec_alloc_context3(codec); if (!c) { fprintf(stderr, "Could not alloc an encoding context\n"); exit(1); } ost->enc = c; /* put sample parameters */ c->sample_fmt = codec->sample_fmts ? codec->sample_fmts[0] : AV_SAMPLE_FMT_S16; c->sample_rate = codec->supported_samplerates ? codec->supported_samplerates[0] : 44100; c->channel_layout = codec->channel_layouts ? codec->channel_layouts[0] : AV_CH_LAYOUT_STEREO; c->channels = av_get_channel_layout_nb_channels(c->channel_layout); c->bit_rate = 64000; ost->st->time_base = (AVRational){ 1, c->sample_rate }; // some formats want stream headers to be separate if (oc->oformat->flags & AVFMT_GLOBALHEADER) c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; /* initialize sample format conversion; * to simplify the code, we always pass the data through lavr, even * if the encoder supports the generated format directly -- the price is * some extra data copying; */ ost->avr = avresample_alloc_context(); if (!ost->avr) { fprintf(stderr, "Error allocating the resampling context\n"); exit(1); } av_opt_set_int(ost->avr, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0); av_opt_set_int(ost->avr, "in_sample_rate", 44100, 0); av_opt_set_int(ost->avr, "in_channel_layout", AV_CH_LAYOUT_STEREO, 0); av_opt_set_int(ost->avr, "out_sample_fmt", c->sample_fmt, 0); av_opt_set_int(ost->avr, "out_sample_rate", c->sample_rate, 0); av_opt_set_int(ost->avr, "out_channel_layout", c->channel_layout, 0); ret = avresample_open(ost->avr); if (ret < 0) { fprintf(stderr, "Error opening the resampling context\n"); exit(1); } }
int hb_audio_resample_update(hb_audio_resample_t *resample) { if (resample == NULL) { hb_error("hb_audio_resample_update: resample is NULL"); return 1; } int ret, resample_changed; resample->resample_needed = (resample->out.sample_fmt != resample->in.sample_fmt || resample->out.channel_layout != resample->in.channel_layout); resample_changed = (resample->resample_needed && (resample->resample.sample_fmt != resample->in.sample_fmt || resample->resample.channel_layout != resample->in.channel_layout || resample->resample.lfe_mix_level != resample->in.lfe_mix_level || resample->resample.center_mix_level != resample->in.center_mix_level || resample->resample.surround_mix_level != resample->in.surround_mix_level)); if (resample_changed || (resample->resample_needed && resample->avresample == NULL)) { if (resample->avresample == NULL) { resample->avresample = avresample_alloc_context(); if (resample->avresample == NULL) { hb_error("hb_audio_resample_update: avresample_alloc_context() failed"); return 1; } av_opt_set_int(resample->avresample, "out_sample_fmt", resample->out.sample_fmt, 0); av_opt_set_int(resample->avresample, "out_channel_layout", resample->out.channel_layout, 0); av_opt_set_int(resample->avresample, "matrix_encoding", resample->out.matrix_encoding, 0); av_opt_set_int(resample->avresample, "normalize_mix_level", resample->out.normalize_mix_level, 0); } else if (resample_changed) { avresample_close(resample->avresample); } av_opt_set_int(resample->avresample, "in_sample_fmt", resample->in.sample_fmt, 0); av_opt_set_int(resample->avresample, "in_channel_layout", resample->in.channel_layout, 0); av_opt_set_double(resample->avresample, "lfe_mix_level", resample->in.lfe_mix_level, 0); av_opt_set_double(resample->avresample, "center_mix_level", resample->in.center_mix_level, 0); av_opt_set_double(resample->avresample, "surround_mix_level", resample->in.surround_mix_level, 0); if ((ret = avresample_open(resample->avresample))) { char err_desc[64]; av_strerror(ret, err_desc, 63); hb_error("hb_audio_resample_update: avresample_open() failed (%s)", err_desc); // avresample won't open, start over avresample_free(&resample->avresample); return ret; } resample->resample.sample_fmt = resample->in.sample_fmt; resample->resample.channel_layout = resample->in.channel_layout; resample->resample.channels = av_get_channel_layout_nb_channels(resample->in.channel_layout); resample->resample.lfe_mix_level = resample->in.lfe_mix_level; resample->resample.center_mix_level = resample->in.center_mix_level; resample->resample.surround_mix_level = resample->in.surround_mix_level; } 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 ) ); } }
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; }
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 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); } } }