int groove_fingerprinter_attach(struct GrooveFingerprinter *printer, struct GroovePlaylist *playlist) { struct GrooveFingerprinterPrivate *p = (struct GrooveFingerprinterPrivate *) printer; printer->playlist = playlist; groove_queue_reset(p->info_queue); p->chroma_ctx = chromaprint_new(CHROMAPRINT_ALGORITHM_DEFAULT); if (!p->chroma_ctx) { groove_fingerprinter_detach(printer); return GrooveErrorNoMem; } int err; if ((err = groove_sink_attach(p->sink, playlist))) { groove_fingerprinter_detach(printer); return err; } if (pthread_create(&p->thread_id, NULL, print_thread, printer)) { groove_fingerprinter_detach(printer); return GrooveErrorSystemResources; } return 0; }
int groove_encoder_attach(struct GrooveEncoder *encoder, struct GroovePlaylist *playlist) { struct GrooveEncoderPrivate *e = (struct GrooveEncoderPrivate *) encoder; encoder->playlist = playlist; groove_queue_reset(e->audioq); e->oformat = av_guess_format(encoder->format_short_name, encoder->filename, encoder->mime_type); if (!e->oformat) { groove_encoder_detach(encoder); av_log(NULL, AV_LOG_ERROR, "unable to determine format\n"); return -1; } // av_guess_codec ignores mime_type, filename, and codec_short_name. see // https://trac.ffmpeg.org/ticket/4706 // because of this we do a workaround to return the correct codec based on // the codec_short_name. AVCodec *codec = NULL; if (encoder->codec_short_name) { codec = avcodec_find_encoder_by_name(encoder->codec_short_name); if (!codec) { const AVCodecDescriptor *desc = avcodec_descriptor_get_by_name(encoder->codec_short_name); if (desc) { codec = avcodec_find_encoder(desc->id); } } } if (!codec) { enum AVCodecID codec_id = av_guess_codec(e->oformat, encoder->codec_short_name, encoder->filename, encoder->mime_type, AVMEDIA_TYPE_AUDIO); codec = avcodec_find_encoder(codec_id); if (!codec) { groove_encoder_detach(encoder); av_log(NULL, AV_LOG_ERROR, "unable to find encoder\n"); return -1; } } e->codec = codec; av_log(NULL, AV_LOG_INFO, "encoder: using codec: %s\n", codec->long_name); encoder->actual_audio_format.sample_fmt = closest_supported_sample_fmt( codec, encoder->target_audio_format.sample_fmt); encoder->actual_audio_format.sample_rate = closest_supported_sample_rate( codec, encoder->target_audio_format.sample_rate); encoder->actual_audio_format.channel_layout = closest_supported_channel_layout( codec, encoder->target_audio_format.channel_layout); log_audio_fmt(&encoder->actual_audio_format); int err = init_avcontext(encoder); if (err < 0) { groove_encoder_detach(encoder); return err; } e->sink->audio_format = encoder->actual_audio_format; e->sink->buffer_size = encoder->sink_buffer_size; e->sink->buffer_sample_count = (codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) ? 0 : e->stream->codec->frame_size; e->sink->gain = encoder->gain; if (groove_sink_attach(e->sink, playlist) < 0) { groove_encoder_detach(encoder); av_log(NULL, AV_LOG_ERROR, "unable to attach sink\n"); return -1; } if (pthread_create(&e->thread_id, NULL, encode_thread, encoder) != 0) { groove_encoder_detach(encoder); av_log(NULL, AV_LOG_ERROR, "unable to create encoder thread\n"); return -1; } return 0; }