static void swap_sample_fmts_on_filter(AVFilterContext *filter) { AVFilterLink *link = NULL; int format, bps; int i, j; for (i = 0; i < filter->nb_inputs; i++) { link = filter->inputs[i]; if (link->type == AVMEDIA_TYPE_AUDIO && link->out_formats->format_count == 1) break; } if (i == filter->nb_inputs) return; format = link->out_formats->formats[0]; bps = av_get_bytes_per_sample(format); for (i = 0; i < filter->nb_outputs; i++) { AVFilterLink *outlink = filter->outputs[i]; int best_idx = -1, best_score = INT_MIN; if (outlink->type != AVMEDIA_TYPE_AUDIO || outlink->in_formats->format_count < 2) continue; for (j = 0; j < outlink->in_formats->format_count; j++) { int out_format = outlink->in_formats->formats[j]; int out_bps = av_get_bytes_per_sample(out_format); int score; if (av_get_packed_sample_fmt(out_format) == format || av_get_planar_sample_fmt(out_format) == format) { best_idx = j; break; } /* for s32 and float prefer double to prevent loss of information */ if (bps == 4 && out_bps == 8) { best_idx = j; break; } /* prefer closest higher or equal bps */ score = -abs(out_bps - bps); if (out_bps >= bps) score += INT_MAX/2; if (score > best_score) { best_score = score; best_idx = j; } } av_assert0(best_idx >= 0); FFSWAP(int, outlink->in_formats->formats[0], outlink->in_formats->formats[best_idx]); } }
bool AVFormatWriter::OpenAudio(void) { AVCodecContext *c; AVCodec *codec; c = m_audioStream->codec; c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; codec = avcodec_find_encoder(c->codec_id); if (!codec) { LOG(VB_RECORD, LOG_ERR, LOC + "OpenAudio(): avcodec_find_encoder() failed"); return false; } // try to find suitable format we can use. avcodec_open2 will fail if we don't // find one, so no need to worry otherwise. Can only handle S16 or FLOAT // we give priority to S16 as libmp3lame requires aligned floats which we can't guarantee if (!FindAudioFormat(c, codec, AV_SAMPLE_FMT_S16)) { FindAudioFormat(c, codec, AV_SAMPLE_FMT_FLT); } if (avcodec_open2(c, codec, NULL) < 0) { LOG(VB_RECORD, LOG_ERR, LOC + "OpenAudio(): avcodec_open() failed"); return false; } m_audioFrameSize = c->frame_size; // number of *samples* per channel in an AVFrame m_audPicture = av_frame_alloc(); if (!m_audPicture) { LOG(VB_RECORD, LOG_ERR, LOC + "OpenAudio(): alloc_frame() failed"); return false; } int samples_per_frame = m_audioFrameSize * m_audioChannels; int bps = av_get_bytes_per_sample(c->sample_fmt); if (av_get_packed_sample_fmt(c->sample_fmt) == AV_SAMPLE_FMT_FLT) { // allocate buffer to convert from S16 to float if (!(m_audioInBuf = (unsigned char*)av_malloc(bps * samples_per_frame))) return false; } if (av_sample_fmt_is_planar(c->sample_fmt)) { // allocate buffer to convert interleaved to planar audio if (!(m_audioInPBuf = (unsigned char*)av_malloc(bps * samples_per_frame))) return false; } return true; }
AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map) { AudioConvert *ac; int in_planar, out_planar; ac = av_mallocz(sizeof(*ac)); if (!ac) return NULL; ac->avr = avr; ac->out_fmt = out_fmt; ac->in_fmt = in_fmt; ac->channels = channels; ac->apply_map = apply_map; if (avr->dither_method != AV_RESAMPLE_DITHER_NONE && av_get_packed_sample_fmt(out_fmt) == AV_SAMPLE_FMT_S16 && av_get_bytes_per_sample(in_fmt) > 2) { ac->dc = ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map); if (!ac->dc) { av_free(ac); return NULL; } return ac; } in_planar = ff_sample_fmt_is_planar(in_fmt, channels); out_planar = ff_sample_fmt_is_planar(out_fmt, channels); if (in_planar == out_planar) { ac->func_type = CONV_FUNC_TYPE_FLAT; ac->planes = in_planar ? ac->channels : 1; } else if (in_planar) ac->func_type = CONV_FUNC_TYPE_INTERLEAVE; else ac->func_type = CONV_FUNC_TYPE_DEINTERLEAVE; set_generic_function(ac); if (ARCH_AARCH64) ff_audio_convert_init_aarch64(ac); if (ARCH_ARM) ff_audio_convert_init_arm(ac); if (ARCH_X86) ff_audio_convert_init_x86(ac); return ac; }
bool AVFormatWriter::FindAudioFormat(AVCodecContext *ctx, AVCodec *c, AVSampleFormat format) { if (c->sample_fmts) { for (int i = 0; c->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) { if (av_get_packed_sample_fmt(c->sample_fmts[i]) == format) { ctx->sample_fmt = c->sample_fmts[i]; return true; } } } return false; }
void FillAP(FFMS_AudioProperties &AP, AVCodecContext *CTX, FFMS_Track &Frames) { AP.SampleFormat = static_cast<FFMS_SampleFormat>(av_get_packed_sample_fmt(CTX->sample_fmt)); AP.BitsPerSample = av_get_bytes_per_sample(CTX->sample_fmt) * 8; AP.Channels = CTX->channels; AP.ChannelLayout = CTX->channel_layout; AP.SampleRate = CTX->sample_rate; if (!Frames.empty()) { AP.NumSamples = (Frames.back()).SampleStart + (Frames.back()).SampleCount; AP.FirstTime = ((Frames.front().PTS * Frames.TB.Num) / (double)Frames.TB.Den) / 1000; AP.LastTime = ((Frames.back().PTS * Frames.TB.Num) / (double)Frames.TB.Den) / 1000; } if (AP.ChannelLayout == 0) AP.ChannelLayout = av_get_default_channel_layout(AP.Channels); }
AudioConvert *swri_audio_convert_alloc(enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, const int *ch_map, int flags) { AudioConvert *ctx; conv_func_type *f = fmt_pair_to_conv_functions[av_get_packed_sample_fmt(out_fmt) + AV_SAMPLE_FMT_NB*av_get_packed_sample_fmt(in_fmt)]; if (!f) return NULL; ctx = av_mallocz(sizeof(*ctx)); if (!ctx) return NULL; if(channels == 1){ in_fmt = av_get_planar_sample_fmt( in_fmt); out_fmt = av_get_planar_sample_fmt(out_fmt); } ctx->channels = channels; ctx->conv_f = f; ctx->ch_map = ch_map; if (in_fmt == AV_SAMPLE_FMT_U8 || in_fmt == AV_SAMPLE_FMT_U8P) memset(ctx->silence, 0x80, sizeof(ctx->silence)); if(out_fmt == in_fmt && !ch_map) { switch(av_get_bytes_per_sample(in_fmt)){ case 1:ctx->simd_f = cpy1; break; case 2:ctx->simd_f = cpy2; break; case 4:ctx->simd_f = cpy4; break; case 8:ctx->simd_f = cpy8; break; } } #if (HAVE_YASM == 1) && (HAVE_MMX == 1) if(HAVE_YASM && HAVE_MMX) swri_audio_convert_init_x86(ctx, out_fmt, in_fmt, channels); #endif #if (ARCH_ARM == 1) if(ARCH_ARM) swri_audio_convert_init_arm(ctx, out_fmt, in_fmt, channels); #endif #if (ARCH_AARCH64 == 1) if(ARCH_AARCH64) swri_audio_convert_init_aarch64(ctx, out_fmt, in_fmt, channels); #endif return ctx; }
int BKE_ffmpeg_start(void *context_v, struct Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports, bool preview, const char *suffix) { int success; FFMpegContext *context = context_v; context->ffmpeg_autosplit_count = 0; context->ffmpeg_preview = preview; success = start_ffmpeg_impl(context, rd, rectx, recty, suffix, reports); #ifdef WITH_AUDASPACE if (context->audio_stream) { AVCodecContext *c = context->audio_stream->codec; AUD_DeviceSpecs specs; specs.channels = c->channels; switch (av_get_packed_sample_fmt(c->sample_fmt)) { case AV_SAMPLE_FMT_U8: specs.format = AUD_FORMAT_U8; break; case AV_SAMPLE_FMT_S16: specs.format = AUD_FORMAT_S16; break; case AV_SAMPLE_FMT_S32: specs.format = AUD_FORMAT_S32; break; case AV_SAMPLE_FMT_FLT: specs.format = AUD_FORMAT_FLOAT32; break; case AV_SAMPLE_FMT_DBL: specs.format = AUD_FORMAT_FLOAT64; break; default: return -31415; } specs.rate = rd->ffcodecdata.audio_mixrate; context->audio_mixdown_device = BKE_sound_mixdown(scene, specs, preview ? rd->psfra : rd->sfra, rd->ffcodecdata.audio_volume); #ifdef FFMPEG_CODEC_TIME_BASE c->time_base.den = specs.rate; c->time_base.num = 1; #endif } #endif return success; }
/** * Allocates and initializes the SwrContext so that we don't have to deal with planar sample formats. * * @param env JNIEnv * @param aio FFAudioIO * @return a negative value should an error occur */ static int init_swr(JNIEnv *env, FFAudioIO *aio) { int res = 0; aio->swr_context = swr_alloc(); if (!aio->swr_context) { res = AVERROR(ENOMEM); throwIOExceptionIfError(env, res, "Could not allocate swr context."); goto bail; } av_opt_set_sample_fmt(aio->swr_context, "in_sample_fmt", aio->stream->codecpar->format, 0); // make sure we get interleaved/packed output av_opt_set_sample_fmt(aio->swr_context, "out_sample_fmt", av_get_packed_sample_fmt(aio->stream->codecpar->format), 0); // keep everything else the way it was... av_opt_set_int(aio->swr_context, "in_channel_count", aio->stream->codecpar->channels, 0); av_opt_set_int(aio->swr_context, "out_channel_count", aio->stream->codecpar->channels, 0); av_opt_set_int(aio->swr_context, "in_channel_layout", aio->stream->codecpar->channel_layout, 0); av_opt_set_int(aio->swr_context, "out_channel_layout", aio->stream->codecpar->channel_layout, 0); av_opt_set_int(aio->swr_context, "in_sample_rate", aio->stream->codecpar->sample_rate, 0); av_opt_set_int(aio->swr_context, "out_sample_rate", aio->stream->codecpar->sample_rate, 0); res = swr_init(aio->swr_context); if (res < 0) { res = AVERROR(ENOMEM); throwIOExceptionIfError(env, res, "Could not initialize swr context"); goto bail; } //fprintf(stderr, "init_swr: dither context: %d\n", aio->swr_context->dither); //fprintf(stderr, "init_swr: output sample bits: %d\n", aio->swr_context->dither.output_sample_bits); bail: return res; }
int AVFormatWriter::WriteAudioFrame(unsigned char *buf, int fnum, long long &timecode) { #if HAVE_BIGENDIAN bswap_16_buf((short int*) buf, m_audioFrameSize, m_audioChannels); #endif int got_packet = 0; int ret = 0; int samples_per_avframe = m_audioFrameSize * m_audioChannels; int sampleSizeIn = AudioOutputSettings::SampleSize(FORMAT_S16); AudioFormat format = AudioOutputSettings::AVSampleFormatToFormat(m_audioStream->codec->sample_fmt); int sampleSizeOut = AudioOutputSettings::SampleSize(format); AVPacket pkt; av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; if (av_get_packed_sample_fmt(m_audioStream->codec->sample_fmt) == AV_SAMPLE_FMT_FLT) { AudioOutputUtil::toFloat(FORMAT_S16, (void *)m_audioInBuf, (void *)buf, samples_per_avframe * sampleSizeIn); buf = m_audioInBuf; } if (av_sample_fmt_is_planar(m_audioStream->codec->sample_fmt)) { AudioOutputUtil::DeinterleaveSamples(format, m_audioChannels, m_audioInPBuf, buf, samples_per_avframe * sampleSizeOut); // init AVFrame for planar data (input is interleaved) for (int j = 0, jj = 0; j < m_audioChannels; j++, jj += m_audioFrameSize) { m_audPicture->data[j] = (uint8_t*)(m_audioInPBuf + jj * sampleSizeOut); } } else { m_audPicture->data[0] = buf; } m_audPicture->linesize[0] = m_audioFrameSize; m_audPicture->nb_samples = m_audioFrameSize; m_audPicture->format = m_audioStream->codec->sample_fmt; m_audPicture->extended_data = m_audPicture->data; m_bufferedAudioFrameTimes.push_back(timecode); { QMutexLocker locker(avcodeclock); ret = avcodec_encode_audio2(m_audioStream->codec, &pkt, m_audPicture, &got_packet); } if (ret < 0) { LOG(VB_RECORD, LOG_ERR, "avcodec_encode_audio2() failed"); return ret; } if (!got_packet) { //LOG(VB_RECORD, LOG_ERR, QString("WriteAudioFrame(): Frame Buffered: cs: %1, mfw: %2, f->tc: %3, fn: %4").arg(m_audPkt->size).arg(m_framesWritten).arg(timecode).arg(fnum)); return ret; } long long tc = timecode; if (m_bufferedAudioFrameTimes.size()) tc = m_bufferedAudioFrameTimes.takeFirst(); if (m_startingTimecodeOffset == -1) m_startingTimecodeOffset = tc - 1; tc -= m_startingTimecodeOffset; if (m_avVideoCodec) pkt.pts = tc * m_videoStream->time_base.den / m_videoStream->time_base.num / 1000; else pkt.pts = tc * m_audioStream->time_base.den / m_audioStream->time_base.num / 1000; pkt.dts = AV_NOPTS_VALUE; pkt.flags |= AV_PKT_FLAG_KEY; pkt.stream_index = m_audioStream->index; //LOG(VB_RECORD, LOG_ERR, QString("WriteAudioFrame(): cs: %1, mfw: %2, pkt->pts: %3, tc: %4, fn: %5, f->tc: %6").arg(m_audPkt->size).arg(m_framesWritten).arg(m_audPkt->pts).arg(tc).arg(fnum).arg(timecode)); ret = av_interleaved_write_frame(m_ctx, &pkt); if (ret != 0) LOG(VB_RECORD, LOG_ERR, LOC + "WriteAudioFrame(): " "av_interleaved_write_frame couldn't write Audio"); timecode = tc + m_startingTimecodeOffset; av_packet_unref(&pkt); return 1; }
av_cold static int auto_matrix(SwrContext *s) { int i, j, out_i; double matrix[NUM_NAMED_CHANNELS][NUM_NAMED_CHANNELS]={{0}}; int64_t unaccounted, in_ch_layout, out_ch_layout; double maxcoef=0; char buf[128]; const int matrix_encoding = s->matrix_encoding; float maxval; in_ch_layout = clean_layout(s, s->in_ch_layout); out_ch_layout = clean_layout(s, s->out_ch_layout); if( out_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX && (in_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0 ) out_ch_layout = AV_CH_LAYOUT_STEREO; if( in_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX && (out_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0 ) in_ch_layout = AV_CH_LAYOUT_STEREO; if(!sane_layout(in_ch_layout)){ av_get_channel_layout_string(buf, sizeof(buf), -1, s->in_ch_layout); av_log(s, AV_LOG_ERROR, "Input channel layout '%s' is not supported\n", buf); return AVERROR(EINVAL); } if(!sane_layout(out_ch_layout)){ av_get_channel_layout_string(buf, sizeof(buf), -1, s->out_ch_layout); av_log(s, AV_LOG_ERROR, "Output channel layout '%s' is not supported\n", buf); return AVERROR(EINVAL); } memset(s->matrix, 0, sizeof(s->matrix)); for(i=0; i<FF_ARRAY_ELEMS(matrix); i++){ if(in_ch_layout & out_ch_layout & (1ULL<<i)) matrix[i][i]= 1.0; } unaccounted= in_ch_layout & ~out_ch_layout; //FIXME implement dolby surround //FIXME implement full ac3 if(unaccounted & AV_CH_FRONT_CENTER){ if((out_ch_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){ if(in_ch_layout & AV_CH_LAYOUT_STEREO) { matrix[ FRONT_LEFT][FRONT_CENTER]+= s->clev; matrix[FRONT_RIGHT][FRONT_CENTER]+= s->clev; } else { matrix[ FRONT_LEFT][FRONT_CENTER]+= M_SQRT1_2; matrix[FRONT_RIGHT][FRONT_CENTER]+= M_SQRT1_2; } }else av_assert0(0); } if(unaccounted & AV_CH_LAYOUT_STEREO){ if(out_ch_layout & AV_CH_FRONT_CENTER){ matrix[FRONT_CENTER][ FRONT_LEFT]+= M_SQRT1_2; matrix[FRONT_CENTER][FRONT_RIGHT]+= M_SQRT1_2; if(in_ch_layout & AV_CH_FRONT_CENTER) matrix[FRONT_CENTER][ FRONT_CENTER] = s->clev*sqrt(2); }else av_assert0(0); } if(unaccounted & AV_CH_BACK_CENTER){ if(out_ch_layout & AV_CH_BACK_LEFT){ matrix[ BACK_LEFT][BACK_CENTER]+= M_SQRT1_2; matrix[BACK_RIGHT][BACK_CENTER]+= M_SQRT1_2; }else if(out_ch_layout & AV_CH_SIDE_LEFT){ matrix[ SIDE_LEFT][BACK_CENTER]+= M_SQRT1_2; matrix[SIDE_RIGHT][BACK_CENTER]+= M_SQRT1_2; }else if(out_ch_layout & AV_CH_FRONT_LEFT){ if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY || matrix_encoding == AV_MATRIX_ENCODING_DPLII) { if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) { matrix[FRONT_LEFT ][BACK_CENTER] -= s->slev * M_SQRT1_2; matrix[FRONT_RIGHT][BACK_CENTER] += s->slev * M_SQRT1_2; } else { matrix[FRONT_LEFT ][BACK_CENTER] -= s->slev; matrix[FRONT_RIGHT][BACK_CENTER] += s->slev; } } else { matrix[ FRONT_LEFT][BACK_CENTER]+= s->slev*M_SQRT1_2; matrix[FRONT_RIGHT][BACK_CENTER]+= s->slev*M_SQRT1_2; } }else if(out_ch_layout & AV_CH_FRONT_CENTER){ matrix[ FRONT_CENTER][BACK_CENTER]+= s->slev*M_SQRT1_2; }else av_assert0(0); } if(unaccounted & AV_CH_BACK_LEFT){ if(out_ch_layout & AV_CH_BACK_CENTER){ matrix[BACK_CENTER][ BACK_LEFT]+= M_SQRT1_2; matrix[BACK_CENTER][BACK_RIGHT]+= M_SQRT1_2; }else if(out_ch_layout & AV_CH_SIDE_LEFT){ if(in_ch_layout & AV_CH_SIDE_LEFT){ matrix[ SIDE_LEFT][ BACK_LEFT]+= M_SQRT1_2; matrix[SIDE_RIGHT][BACK_RIGHT]+= M_SQRT1_2; }else{ matrix[ SIDE_LEFT][ BACK_LEFT]+= 1.0; matrix[SIDE_RIGHT][BACK_RIGHT]+= 1.0; } }else if(out_ch_layout & AV_CH_FRONT_LEFT){ if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) { matrix[FRONT_LEFT ][BACK_LEFT ] -= s->slev * M_SQRT1_2; matrix[FRONT_LEFT ][BACK_RIGHT] -= s->slev * M_SQRT1_2; matrix[FRONT_RIGHT][BACK_LEFT ] += s->slev * M_SQRT1_2; matrix[FRONT_RIGHT][BACK_RIGHT] += s->slev * M_SQRT1_2; } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) { matrix[FRONT_LEFT ][BACK_LEFT ] -= s->slev * SQRT3_2; matrix[FRONT_LEFT ][BACK_RIGHT] -= s->slev * M_SQRT1_2; matrix[FRONT_RIGHT][BACK_LEFT ] += s->slev * M_SQRT1_2; matrix[FRONT_RIGHT][BACK_RIGHT] += s->slev * SQRT3_2; } else { matrix[ FRONT_LEFT][ BACK_LEFT] += s->slev; matrix[FRONT_RIGHT][BACK_RIGHT] += s->slev; } }else if(out_ch_layout & AV_CH_FRONT_CENTER){ matrix[ FRONT_CENTER][BACK_LEFT ]+= s->slev*M_SQRT1_2; matrix[ FRONT_CENTER][BACK_RIGHT]+= s->slev*M_SQRT1_2; }else av_assert0(0); } if(unaccounted & AV_CH_SIDE_LEFT){ if(out_ch_layout & AV_CH_BACK_LEFT){ /* if back channels do not exist in the input, just copy side channels to back channels, otherwise mix side into back */ if (in_ch_layout & AV_CH_BACK_LEFT) { matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2; matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2; } else { matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0; matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0; } }else if(out_ch_layout & AV_CH_BACK_CENTER){ matrix[BACK_CENTER][ SIDE_LEFT]+= M_SQRT1_2; matrix[BACK_CENTER][SIDE_RIGHT]+= M_SQRT1_2; }else if(out_ch_layout & AV_CH_FRONT_LEFT){ if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) { matrix[FRONT_LEFT ][SIDE_LEFT ] -= s->slev * M_SQRT1_2; matrix[FRONT_LEFT ][SIDE_RIGHT] -= s->slev * M_SQRT1_2; matrix[FRONT_RIGHT][SIDE_LEFT ] += s->slev * M_SQRT1_2; matrix[FRONT_RIGHT][SIDE_RIGHT] += s->slev * M_SQRT1_2; } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) { matrix[FRONT_LEFT ][SIDE_LEFT ] -= s->slev * SQRT3_2; matrix[FRONT_LEFT ][SIDE_RIGHT] -= s->slev * M_SQRT1_2; matrix[FRONT_RIGHT][SIDE_LEFT ] += s->slev * M_SQRT1_2; matrix[FRONT_RIGHT][SIDE_RIGHT] += s->slev * SQRT3_2; } else { matrix[ FRONT_LEFT][ SIDE_LEFT] += s->slev; matrix[FRONT_RIGHT][SIDE_RIGHT] += s->slev; } }else if(out_ch_layout & AV_CH_FRONT_CENTER){ matrix[ FRONT_CENTER][SIDE_LEFT ]+= s->slev*M_SQRT1_2; matrix[ FRONT_CENTER][SIDE_RIGHT]+= s->slev*M_SQRT1_2; }else av_assert0(0); } if(unaccounted & AV_CH_FRONT_LEFT_OF_CENTER){ if(out_ch_layout & AV_CH_FRONT_LEFT){ matrix[ FRONT_LEFT][ FRONT_LEFT_OF_CENTER]+= 1.0; matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER]+= 1.0; }else if(out_ch_layout & AV_CH_FRONT_CENTER){ matrix[ FRONT_CENTER][ FRONT_LEFT_OF_CENTER]+= M_SQRT1_2; matrix[ FRONT_CENTER][FRONT_RIGHT_OF_CENTER]+= M_SQRT1_2; }else av_assert0(0); } /* mix LFE into front left/right or center */ if (unaccounted & AV_CH_LOW_FREQUENCY) { if (out_ch_layout & AV_CH_FRONT_CENTER) { matrix[FRONT_CENTER][LOW_FREQUENCY] += s->lfe_mix_level; } else if (out_ch_layout & AV_CH_FRONT_LEFT) { matrix[FRONT_LEFT ][LOW_FREQUENCY] += s->lfe_mix_level * M_SQRT1_2; matrix[FRONT_RIGHT][LOW_FREQUENCY] += s->lfe_mix_level * M_SQRT1_2; } else av_assert0(0); } for(out_i=i=0; i<64; i++){ double sum=0; int in_i=0; if((out_ch_layout & (1ULL<<i)) == 0) continue; for(j=0; j<64; j++){ if((in_ch_layout & (1ULL<<j)) == 0) continue; if (i < FF_ARRAY_ELEMS(matrix) && j < FF_ARRAY_ELEMS(matrix[0])) s->matrix[out_i][in_i]= matrix[i][j]; else s->matrix[out_i][in_i]= i == j && (in_ch_layout & out_ch_layout & (1ULL<<i)); sum += fabs(s->matrix[out_i][in_i]); in_i++; } maxcoef= FFMAX(maxcoef, sum); out_i++; } if(s->rematrix_volume < 0) maxcoef = -s->rematrix_volume; if (s->rematrix_maxval > 0) { maxval = s->rematrix_maxval; } else if ( av_get_packed_sample_fmt(s->out_sample_fmt) < AV_SAMPLE_FMT_FLT || av_get_packed_sample_fmt(s->int_sample_fmt) < AV_SAMPLE_FMT_FLT) { maxval = 1.0; } else maxval = INT_MAX; if(maxcoef > maxval || s->rematrix_volume < 0){ maxcoef /= maxval; for(i=0; i<SWR_CH_MAX; i++) for(j=0; j<SWR_CH_MAX; j++){ s->matrix[i][j] /= maxcoef; } } if(s->rematrix_volume > 0){ for(i=0; i<SWR_CH_MAX; i++) for(j=0; j<SWR_CH_MAX; j++){ s->matrix[i][j] *= s->rematrix_volume; } } av_log(s, AV_LOG_DEBUG, "Matrix coefficients:\n"); for(i=0; i<av_get_channel_layout_nb_channels(out_ch_layout); i++){ const char *c = av_get_channel_name(av_channel_layout_extract_channel(out_ch_layout, i)); av_log(s, AV_LOG_DEBUG, "%s: ", c ? c : "?"); for(j=0; j<av_get_channel_layout_nb_channels(in_ch_layout); j++){ c = av_get_channel_name(av_channel_layout_extract_channel(in_ch_layout, j)); av_log(s, AV_LOG_DEBUG, "%s:%f ", c ? c : "?", s->matrix[i][j]); } av_log(s, AV_LOG_DEBUG, "\n"); } return 0; }
int main (int argc, char **argv) { int ret = 0, got_frame; if (argc != 4 && argc != 5) { fprintf(stderr, "usage: %s [-refcount] input_file video_output_file audio_output_file\n" "API example program to show how to read frames from an input file.\n" "This program reads frames from a file, decodes them, and writes decoded\n" "video frames to a rawvideo file named video_output_file, and decoded\n" "audio frames to a rawaudio file named audio_output_file.\n\n" "If the -refcount option is specified, the program use the\n" "reference counting frame system which allows keeping a copy of\n" "the data for longer than one decode call.\n" "\n", argv[0]); exit(1); } if (argc == 5 && !strcmp(argv[1], "-refcount")) { refcount = 1; argv++; } src_filename = argv[1]; video_dst_filename = argv[2]; audio_dst_filename = argv[3]; /* register all formats and codecs */ av_register_all(); /* open input file, and allocate format context */ if (avformat_open_input(&fmt_ctx, src_filename, NULL, NULL) < 0) { fprintf(stderr, "Could not open source file %s\n", src_filename); exit(1); } /* retrieve stream information */ if (avformat_find_stream_info(fmt_ctx, NULL) < 0) { fprintf(stderr, "Could not find stream information\n"); exit(1); } if (open_codec_context(&video_stream_idx, fmt_ctx, AVMEDIA_TYPE_VIDEO) >= 0) { video_stream = fmt_ctx->streams[video_stream_idx]; video_dec_ctx = video_stream->codec; video_dst_file = fopen(video_dst_filename, "wb"); if (!video_dst_file) { fprintf(stderr, "Could not open destination file %s\n", video_dst_filename); ret = 1; goto end; } /* allocate image where the decoded image will be put */ width = video_dec_ctx->width; height = video_dec_ctx->height; pix_fmt = video_dec_ctx->pix_fmt; ret = av_image_alloc(video_dst_data, video_dst_linesize, width, height, pix_fmt, 1); if (ret < 0) { fprintf(stderr, "Could not allocate raw video buffer\n"); goto end; } video_dst_bufsize = ret; } if (open_codec_context(&audio_stream_idx, fmt_ctx, AVMEDIA_TYPE_AUDIO) >= 0) { audio_stream = fmt_ctx->streams[audio_stream_idx]; audio_dec_ctx = audio_stream->codec; audio_dst_file = fopen(audio_dst_filename, "wb"); if (!audio_dst_file) { fprintf(stderr, "Could not open destination file %s\n", audio_dst_filename); ret = 1; goto end; } } /* dump input information to stderr */ av_dump_format(fmt_ctx, 0, src_filename, 0); if (!audio_stream && !video_stream) { fprintf(stderr, "Could not find audio or video stream in the input, aborting\n"); ret = 1; goto end; } frame = av_frame_alloc(); if (!frame) { fprintf(stderr, "Could not allocate frame\n"); ret = AVERROR(ENOMEM); goto end; } /* initialize packet, set data to NULL, let the demuxer fill it */ av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; if (video_stream) printf("Demuxing video from file '%s' into '%s'\n", src_filename, video_dst_filename); if (audio_stream) printf("Demuxing audio from file '%s' into '%s'\n", src_filename, audio_dst_filename); /* read frames from the file */ while (av_read_frame(fmt_ctx, &pkt) >= 0) { AVPacket orig_pkt = pkt; do { ret = decode_packet(&got_frame, 0); if (ret < 0) break; pkt.data += ret; pkt.size -= ret; } while (pkt.size > 0); av_packet_unref(&orig_pkt); } /* flush cached frames */ pkt.data = NULL; pkt.size = 0; do { decode_packet(&got_frame, 1); } while (got_frame); printf("Demuxing succeeded.\n"); if (video_stream) { printf("Play the output video file with the command:\n" "ffplay -f rawvideo -pix_fmt %s -video_size %dx%d %s\n", av_get_pix_fmt_name(pix_fmt), width, height, video_dst_filename); } if (audio_stream) { enum AVSampleFormat sfmt = audio_dec_ctx->sample_fmt; int n_channels = audio_dec_ctx->channels; const char *fmt; if (av_sample_fmt_is_planar(sfmt)) { const char *packed = av_get_sample_fmt_name(sfmt); printf("Warning: the sample format the decoder produced is planar " "(%s). This example will output the first channel only.\n", packed ? packed : "?"); sfmt = av_get_packed_sample_fmt(sfmt); n_channels = 1; } if ((ret = get_format_from_sample_fmt(&fmt, sfmt)) < 0) goto end; printf("Play the output audio file with the command:\n" "ffplay -f %s -ac %d -ar %d %s\n", fmt, n_channels, audio_dec_ctx->sample_rate, audio_dst_filename); } end: avcodec_close(video_dec_ctx); avcodec_close(audio_dec_ctx); avformat_close_input(&fmt_ctx); if (video_dst_file) fclose(video_dst_file); if (audio_dst_file) fclose(audio_dst_file); av_frame_free(&frame); av_free(video_dst_data[0]); return ret < 0; }
DitherContext *ff_dither_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate) { AVLFG seed_gen; DitherContext *c; int ch; if (av_get_packed_sample_fmt(out_fmt) != AV_SAMPLE_FMT_S16 || av_get_bytes_per_sample(in_fmt) <= 2) { av_log(avr, AV_LOG_ERROR, "dithering %s to %s is not supported\n", av_get_sample_fmt_name(in_fmt), av_get_sample_fmt_name(out_fmt)); return NULL; } c = av_mallocz(sizeof(*c)); if (!c) return NULL; if (avr->dither_method == AV_RESAMPLE_DITHER_TRIANGULAR_NS && sample_rate != 48000 && sample_rate != 44100) { av_log(avr, AV_LOG_WARNING, "sample rate must be 48000 or 44100 Hz " "for triangular_ns dither. using triangular_hp instead.\n"); avr->dither_method = AV_RESAMPLE_DITHER_TRIANGULAR_HP; } c->method = avr->dither_method; dither_init(&c->ddsp, c->method); if (c->method == AV_RESAMPLE_DITHER_TRIANGULAR_NS) { if (sample_rate == 48000) { c->ns_coef_b = ns_48_coef_b; c->ns_coef_a = ns_48_coef_a; } else { c->ns_coef_b = ns_44_coef_b; c->ns_coef_a = ns_44_coef_a; } } /* Either s16 or s16p output format is allowed, but s16p is used internally, so we need to use a temp buffer and interleave if the output format is s16 */ if (out_fmt != AV_SAMPLE_FMT_S16P) { c->s16_data = ff_audio_data_alloc(channels, 1024, AV_SAMPLE_FMT_S16P, "dither s16 buffer"); if (!c->s16_data) goto fail; c->ac_out = ff_audio_convert_alloc(avr, out_fmt, AV_SAMPLE_FMT_S16P, channels, sample_rate); if (!c->ac_out) goto fail; } if (in_fmt != AV_SAMPLE_FMT_FLTP) { c->flt_data = ff_audio_data_alloc(channels, 1024, AV_SAMPLE_FMT_FLTP, "dither flt buffer"); if (!c->flt_data) goto fail; c->ac_in = ff_audio_convert_alloc(avr, AV_SAMPLE_FMT_FLTP, in_fmt, channels, sample_rate); if (!c->ac_in) goto fail; } c->state = av_mallocz(channels * sizeof(*c->state)); if (!c->state) goto fail; c->channels = channels; /* calculate thresholds for turning off dithering during periods of silence to avoid replacing digital silence with quiet dither noise */ c->mute_dither_threshold = lrintf(sample_rate * MUTE_THRESHOLD_SEC); c->mute_reset_threshold = c->mute_dither_threshold * 4; /* initialize dither states */ av_lfg_init(&seed_gen, 0xC0FFEE); for (ch = 0; ch < channels; ch++) { DitherState *state = &c->state[ch]; state->mute = c->mute_reset_threshold + 1; state->seed = av_lfg_get(&seed_gen); generate_dither_noise(c, state, FFMAX(32768, sample_rate / 2)); } return c; fail: ff_dither_free(&c); return NULL; }
/* Prefer playing audio with the samplerate given in container data * if available, but take number the number of channels and sample format * from the codec, since if the codec isn't using the correct values for * those everything breaks anyway. */ static int setup_format(sh_audio_t *sh_audio) { struct priv *priv = sh_audio->context; AVCodecContext *codec = priv->avctx; int sample_format = sample_fmt_lavc2native(codec->sample_fmt); if (sample_format == AF_FORMAT_UNKNOWN) { #ifndef CONFIG_LIBAVRESAMPLE if (av_sample_fmt_is_planar(codec->sample_fmt)) mp_msg(MSGT_DECAUDIO, MSGL_ERR, "The player has been compiled without libavresample " "support,\nwhich is needed with this libavcodec decoder " "version.\nCompile with libavresample enabled to make " "audio decoding work!\n"); else mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Unsupported sample format\n"); goto error; #else if (priv->avr && (priv->resample_fmt != codec->sample_fmt || priv->resample_channels != codec->channels)) avresample_free(&priv->avr); if (!priv->avr) { int ret; uint8_t error[128]; enum AVSampleFormat out_fmt = av_get_packed_sample_fmt(codec->sample_fmt); uint64_t ch_layout = codec->channel_layout; mp_msg(MSGT_DECAUDIO, MSGL_V, "(Re)initializing libavresample format conversion...\n"); if (!ch_layout) ch_layout = av_get_default_channel_layout(codec->channels); /* if lavc format is planar, try just getting packed equivalent */ sample_format = sample_fmt_lavc2native(out_fmt); if (sample_format == AF_FORMAT_UNKNOWN) { /* fallback to s16 */ out_fmt = AV_SAMPLE_FMT_S16; sample_format = AF_FORMAT_S16_NE; } priv->avr = avresample_alloc_context(); if (!priv->avr) { mp_msg(MSGT_DECAUDIO, MSGL_FATAL, "Out of memory.\n"); abort(); } av_opt_set_int(priv->avr, "in_channel_layout", ch_layout, 0); av_opt_set_int(priv->avr, "out_channel_layout", ch_layout, 0); av_opt_set_int(priv->avr, "in_sample_rate", codec->sample_rate, 0); av_opt_set_int(priv->avr, "out_sample_rate", codec->sample_rate, 0); av_opt_set_int(priv->avr, "in_sample_fmt", codec->sample_fmt, 0); av_opt_set_int(priv->avr, "out_sample_fmt", out_fmt, 0); if ((ret = avresample_open(priv->avr)) < 0) { av_strerror(ret, error, sizeof(error)); mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Error opening libavresample: %s.\n", error); goto error; } priv->resample_fmt = codec->sample_fmt; priv->resample_channels = codec->channels; priv->out_fmt = out_fmt; priv->unitsize = av_get_bytes_per_sample(out_fmt) * codec->channels; } else sample_format = sh_audio->sample_format; } else if (priv->avr) { avresample_free(&priv->avr); #endif } bool broken_srate = false; int samplerate = codec->sample_rate; int container_samplerate = sh_audio->container_out_samplerate; if (!container_samplerate && sh_audio->wf) container_samplerate = sh_audio->wf->nSamplesPerSec; if (codec->codec_id == AV_CODEC_ID_AAC && samplerate == 2 * container_samplerate) broken_srate = true; else if (container_samplerate) samplerate = container_samplerate; if (codec->channels != sh_audio->channels || samplerate != sh_audio->samplerate || sample_format != sh_audio->sample_format) { sh_audio->channels = codec->channels; sh_audio->samplerate = samplerate; sh_audio->sample_format = sample_format; sh_audio->samplesize = af_fmt2bits(sh_audio->sample_format) / 8; if (broken_srate) mp_msg(MSGT_DECAUDIO, MSGL_WARN, "Ignoring broken container sample rate for AAC with SBR\n"); return 1; } return 0; error: #ifdef CONFIG_LIBAVRESAMPLE avresample_free(&priv->avr); #endif return -1; }
static int auto_matrix(SwrContext *s) { int i, j, out_i; double matrix[64][64]={{0}}; int64_t unaccounted= s->in_ch_layout & ~s->out_ch_layout; double maxcoef=0; memset(s->matrix, 0, sizeof(s->matrix)); for(i=0; i<64; i++){ if(s->in_ch_layout & s->out_ch_layout & (1LL<<i)) matrix[i][i]= 1.0; } if(!sane_layout(s->in_ch_layout)){ av_log(s, AV_LOG_ERROR, "Input channel layout isnt supported\n"); return AVERROR(EINVAL); } if(!sane_layout(s->out_ch_layout)){ av_log(s, AV_LOG_ERROR, "Output channel layout isnt supported\n"); return AVERROR(EINVAL); } //FIXME implement dolby surround //FIXME implement full ac3 if(unaccounted & AV_CH_FRONT_CENTER){ if((s->out_ch_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){ matrix[ FRONT_LEFT][FRONT_CENTER]+= M_SQRT1_2; matrix[FRONT_RIGHT][FRONT_CENTER]+= M_SQRT1_2; }else av_assert0(0); } if(unaccounted & AV_CH_LAYOUT_STEREO){ if(s->out_ch_layout & AV_CH_FRONT_CENTER){ matrix[FRONT_CENTER][ FRONT_LEFT]+= M_SQRT1_2; matrix[FRONT_CENTER][FRONT_RIGHT]+= M_SQRT1_2; if(s->in_ch_layout & AV_CH_FRONT_CENTER) matrix[FRONT_CENTER][ FRONT_CENTER] = s->clev*sqrt(2); }else av_assert0(0); } if(unaccounted & AV_CH_BACK_CENTER){ if(s->out_ch_layout & AV_CH_BACK_LEFT){ matrix[ BACK_LEFT][BACK_CENTER]+= M_SQRT1_2; matrix[BACK_RIGHT][BACK_CENTER]+= M_SQRT1_2; }else if(s->out_ch_layout & AV_CH_SIDE_LEFT){ matrix[ SIDE_LEFT][BACK_CENTER]+= M_SQRT1_2; matrix[SIDE_RIGHT][BACK_CENTER]+= M_SQRT1_2; }else if(s->out_ch_layout & AV_CH_FRONT_LEFT){ matrix[ FRONT_LEFT][BACK_CENTER]+= s->slev*M_SQRT1_2; matrix[FRONT_RIGHT][BACK_CENTER]+= s->slev*M_SQRT1_2; }else if(s->out_ch_layout & AV_CH_FRONT_CENTER){ matrix[ FRONT_CENTER][BACK_CENTER]+= s->slev*M_SQRT1_2; }else av_assert0(0); } if(unaccounted & AV_CH_BACK_LEFT){ if(s->out_ch_layout & AV_CH_BACK_CENTER){ matrix[BACK_CENTER][ BACK_LEFT]+= M_SQRT1_2; matrix[BACK_CENTER][BACK_RIGHT]+= M_SQRT1_2; }else if(s->out_ch_layout & AV_CH_SIDE_LEFT){ if(s->in_ch_layout & AV_CH_SIDE_LEFT){ matrix[ SIDE_LEFT][ BACK_LEFT]+= M_SQRT1_2; matrix[SIDE_RIGHT][BACK_RIGHT]+= M_SQRT1_2; }else{ matrix[ SIDE_LEFT][ BACK_LEFT]+= 1.0; matrix[SIDE_RIGHT][BACK_RIGHT]+= 1.0; } }else if(s->out_ch_layout & AV_CH_FRONT_LEFT){ matrix[ FRONT_LEFT][ BACK_LEFT]+= s->slev; matrix[FRONT_RIGHT][BACK_RIGHT]+= s->slev; }else if(s->out_ch_layout & AV_CH_FRONT_CENTER){ matrix[ FRONT_CENTER][BACK_LEFT ]+= s->slev*M_SQRT1_2; matrix[ FRONT_CENTER][BACK_RIGHT]+= s->slev*M_SQRT1_2; }else av_assert0(0); } if(unaccounted & AV_CH_SIDE_LEFT){ if(s->out_ch_layout & AV_CH_BACK_LEFT){ /* if back channels do not exist in the input, just copy side channels to back channels, otherwise mix side into back */ if (s->in_ch_layout & AV_CH_BACK_LEFT) { matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2; matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2; } else { matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0; matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0; } }else if(s->out_ch_layout & AV_CH_BACK_CENTER){ matrix[BACK_CENTER][ SIDE_LEFT]+= M_SQRT1_2; matrix[BACK_CENTER][SIDE_RIGHT]+= M_SQRT1_2; }else if(s->out_ch_layout & AV_CH_FRONT_LEFT){ matrix[ FRONT_LEFT][ SIDE_LEFT]+= s->slev; matrix[FRONT_RIGHT][SIDE_RIGHT]+= s->slev; }else if(s->out_ch_layout & AV_CH_FRONT_CENTER){ matrix[ FRONT_CENTER][SIDE_LEFT ]+= s->slev*M_SQRT1_2; matrix[ FRONT_CENTER][SIDE_RIGHT]+= s->slev*M_SQRT1_2; }else av_assert0(0); } if(unaccounted & AV_CH_FRONT_LEFT_OF_CENTER){ if(s->out_ch_layout & AV_CH_FRONT_LEFT){ matrix[ FRONT_LEFT][ FRONT_LEFT_OF_CENTER]+= 1.0; matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER]+= 1.0; }else if(s->out_ch_layout & AV_CH_FRONT_CENTER){ matrix[ FRONT_CENTER][ FRONT_LEFT_OF_CENTER]+= M_SQRT1_2; matrix[ FRONT_CENTER][FRONT_RIGHT_OF_CENTER]+= M_SQRT1_2; }else av_assert0(0); } /* mix LFE into front left/right or center */ if (unaccounted & AV_CH_LOW_FREQUENCY) { if (s->out_ch_layout & AV_CH_FRONT_CENTER) { matrix[FRONT_CENTER][LOW_FREQUENCY] += s->lfe_mix_level; } else if (s->out_ch_layout & AV_CH_FRONT_LEFT) { matrix[FRONT_LEFT ][LOW_FREQUENCY] += s->lfe_mix_level * M_SQRT1_2; matrix[FRONT_RIGHT][LOW_FREQUENCY] += s->lfe_mix_level * M_SQRT1_2; } else av_assert0(0); } for(out_i=i=0; i<64; i++){ double sum=0; int in_i=0; for(j=0; j<64; j++){ s->matrix[out_i][in_i]= matrix[i][j]; if(matrix[i][j]){ sum += fabs(matrix[i][j]); } if(s->in_ch_layout & (1ULL<<j)) in_i++; } maxcoef= FFMAX(maxcoef, sum); if(s->out_ch_layout & (1ULL<<i)) out_i++; } if(s->rematrix_volume < 0) maxcoef = -s->rematrix_volume; if(( av_get_packed_sample_fmt(s->out_sample_fmt) < AV_SAMPLE_FMT_FLT || av_get_packed_sample_fmt(s->int_sample_fmt) < AV_SAMPLE_FMT_FLT) && maxcoef > 1.0){ for(i=0; i<SWR_CH_MAX; i++) for(j=0; j<SWR_CH_MAX; j++){ s->matrix[i][j] /= maxcoef; } } if(s->rematrix_volume > 0){ for(i=0; i<SWR_CH_MAX; i++) for(j=0; j<SWR_CH_MAX; j++){ s->matrix[i][j] *= s->rematrix_volume; } } for(i=0; i<av_get_channel_layout_nb_channels(s->out_ch_layout); i++){ for(j=0; j<av_get_channel_layout_nb_channels(s->in_ch_layout); j++){ av_log(NULL, AV_LOG_DEBUG, "%f ", s->matrix[i][j]); } av_log(NULL, AV_LOG_DEBUG, "\n"); } return 0; }
static int filter_frame(AVFilterLink *inlink, AVFrame *buf) { VolumeContext *vol = inlink->dst->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; int nb_samples = buf->nb_samples; AVFrame *out_buf; AVFrameSideData *sd = av_frame_get_side_data(buf, AV_FRAME_DATA_REPLAYGAIN); int ret; if (sd && vol->replaygain != REPLAYGAIN_IGNORE) { if (vol->replaygain != REPLAYGAIN_DROP) { AVReplayGain *replaygain = (AVReplayGain*)sd->data; int32_t gain = 100000; uint32_t peak = 100000; float g, p; if (vol->replaygain == REPLAYGAIN_TRACK && replaygain->track_gain != INT32_MIN) { gain = replaygain->track_gain; if (replaygain->track_peak != 0) peak = replaygain->track_peak; } else if (replaygain->album_gain != INT32_MIN) { gain = replaygain->album_gain; if (replaygain->album_peak != 0) peak = replaygain->album_peak; } else { av_log(inlink->dst, AV_LOG_WARNING, "Both ReplayGain gain " "values are unknown.\n"); } g = gain / 100000.0f; p = peak / 100000.0f; av_log(inlink->dst, AV_LOG_VERBOSE, "Using gain %f dB from replaygain side data.\n", g); vol->volume = pow(10, (g + vol->replaygain_preamp) / 20); if (vol->replaygain_noclip) vol->volume = FFMIN(vol->volume, 1.0 / p); vol->volume_i = (int)(vol->volume * 256 + 0.5); volume_init(vol); } av_frame_remove_side_data(buf, AV_FRAME_DATA_REPLAYGAIN); } if (vol->volume == 1.0 || vol->volume_i == 256) return ff_filter_frame(outlink, buf); /* do volume scaling in-place if input buffer is writable */ if (av_frame_is_writable(buf)) { out_buf = buf; } else { out_buf = ff_get_audio_buffer(inlink, nb_samples); if (!out_buf) return AVERROR(ENOMEM); ret = av_frame_copy_props(out_buf, buf); if (ret < 0) { av_frame_free(&out_buf); av_frame_free(&buf); return ret; } } if (vol->precision != PRECISION_FIXED || vol->volume_i > 0) { int p, plane_samples; if (av_sample_fmt_is_planar(buf->format)) plane_samples = FFALIGN(nb_samples, vol->samples_align); else plane_samples = FFALIGN(nb_samples * vol->channels, vol->samples_align); if (vol->precision == PRECISION_FIXED) { for (p = 0; p < vol->planes; p++) { vol->scale_samples(out_buf->extended_data[p], buf->extended_data[p], plane_samples, vol->volume_i); } } else if (av_get_packed_sample_fmt(vol->sample_fmt) == AV_SAMPLE_FMT_FLT) { for (p = 0; p < vol->planes; p++) { vol->fdsp.vector_fmul_scalar((float *)out_buf->extended_data[p], (const float *)buf->extended_data[p], vol->volume, plane_samples); } } else { for (p = 0; p < vol->planes; p++) { vol->fdsp.vector_dmul_scalar((double *)out_buf->extended_data[p], (const double *)buf->extended_data[p], vol->volume, plane_samples); } } } emms_c(); if (buf != out_buf) av_frame_free(&buf); return ff_filter_frame(outlink, out_buf); }
void ff_audio_convert_set_func(AudioConvert *ac, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int ptr_align, int samples_align, const char *descr, void *conv) { int found = 0; switch (ac->func_type) { case CONV_FUNC_TYPE_FLAT: if (av_get_packed_sample_fmt(ac->in_fmt) == in_fmt && av_get_packed_sample_fmt(ac->out_fmt) == out_fmt) { ac->conv_flat = conv; ac->func_descr = descr; ac->ptr_align = ptr_align; ac->samples_align = samples_align; if (ptr_align == 1 && samples_align == 1) { ac->conv_flat_generic = conv; ac->func_descr_generic = descr; } else { ac->has_optimized_func = 1; } found = 1; } break; case CONV_FUNC_TYPE_INTERLEAVE: if (ac->in_fmt == in_fmt && ac->out_fmt == out_fmt && (!channels || ac->channels == channels)) { ac->conv_interleave = conv; ac->func_descr = descr; ac->ptr_align = ptr_align; ac->samples_align = samples_align; if (ptr_align == 1 && samples_align == 1) { ac->conv_interleave_generic = conv; ac->func_descr_generic = descr; } else { ac->has_optimized_func = 1; } found = 1; } break; case CONV_FUNC_TYPE_DEINTERLEAVE: if (ac->in_fmt == in_fmt && ac->out_fmt == out_fmt && (!channels || ac->channels == channels)) { ac->conv_deinterleave = conv; ac->func_descr = descr; ac->ptr_align = ptr_align; ac->samples_align = samples_align; if (ptr_align == 1 && samples_align == 1) { ac->conv_deinterleave_generic = conv; ac->func_descr_generic = descr; } else { ac->has_optimized_func = 1; } found = 1; } break; } if (found) { av_log(ac->avr, AV_LOG_DEBUG, "audio_convert: found function: %-4s " "to %-4s (%s)\n", av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt), descr); } }
void AUD_FFMPEGReader::init() { m_position = 0; m_pkgbuf_left = 0; if(avformat_find_stream_info(m_formatCtx, NULL) < 0) AUD_THROW(AUD_ERROR_FFMPEG, streaminfo_error); // find audio stream and codec m_stream = -1; for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++) { if((m_formatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) && (m_stream < 0)) { m_stream=i; break; } } if(m_stream == -1) AUD_THROW(AUD_ERROR_FFMPEG, noaudio_error); m_codecCtx = m_formatCtx->streams[m_stream]->codec; // get a decoder and open it AVCodec *aCodec = avcodec_find_decoder(m_codecCtx->codec_id); if(!aCodec) AUD_THROW(AUD_ERROR_FFMPEG, nodecoder_error); if(avcodec_open2(m_codecCtx, aCodec, NULL) < 0) AUD_THROW(AUD_ERROR_FFMPEG, codecopen_error); // XXX this prints file information to stdout: //dump_format(m_formatCtx, 0, NULL, 0); m_specs.channels = (AUD_Channels) m_codecCtx->channels; m_tointerleave = av_sample_fmt_is_planar(m_codecCtx->sample_fmt); switch(av_get_packed_sample_fmt(m_codecCtx->sample_fmt)) { case AV_SAMPLE_FMT_U8: m_convert = AUD_convert_u8_float; m_specs.format = AUD_FORMAT_U8; break; case AV_SAMPLE_FMT_S16: m_convert = AUD_convert_s16_float; m_specs.format = AUD_FORMAT_S16; break; case AV_SAMPLE_FMT_S32: m_convert = AUD_convert_s32_float; m_specs.format = AUD_FORMAT_S32; break; case AV_SAMPLE_FMT_FLT: m_convert = AUD_convert_copy<float>; m_specs.format = AUD_FORMAT_FLOAT32; break; case AV_SAMPLE_FMT_DBL: m_convert = AUD_convert_double_float; m_specs.format = AUD_FORMAT_FLOAT64; break; default: AUD_THROW(AUD_ERROR_FFMPEG, format_error); } m_specs.rate = (AUD_SampleRate) m_codecCtx->sample_rate; }
void AudioDecoderThread::decodePacket(AVPacket* pPacket) { char* pDecodedData = 0; AVPacket* pTempPacket = new AVPacket; av_init_packet(pTempPacket); pTempPacket->data = pPacket->data; pTempPacket->size = pPacket->size; AVFrame* pDecodedFrame; pDecodedFrame = avcodec_alloc_frame(); while (pTempPacket->size > 0) { int gotFrame = 0; int bytesDecoded; int bytesConsumed = avcodec_decode_audio4(m_pStream->codec, pDecodedFrame, &gotFrame, pTempPacket); if (gotFrame) { bytesDecoded = av_samples_get_buffer_size(0, m_pStream->codec->channels, pDecodedFrame->nb_samples, m_pStream->codec->sample_fmt, 1); pDecodedData = (char*)(pDecodedFrame->data[0]); } else { bytesDecoded = 0; } // This is triggered for some strange/broken videos. // AVG_ASSERT(bytesConsumed != 0); if (bytesConsumed < 0) { // Error decoding -> throw away current packet. bytesDecoded = 0; pTempPacket->size = 0; } else { pTempPacket->data += bytesConsumed; pTempPacket->size -= bytesConsumed; } if (bytesDecoded > 0) { int framesDecoded = bytesDecoded/(m_pStream->codec->channels* getBytesPerSample(m_InputSampleFormat)); AudioBufferPtr pBuffer; bool bNeedsResample = (m_InputSampleRate != m_AP.m_SampleRate || m_InputSampleFormat != AV_SAMPLE_FMT_S16 || m_pStream->codec->channels != m_AP.m_Channels); bool bIsPlanar = false; #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51, 27, 0) bIsPlanar = av_sample_fmt_is_planar((AVSampleFormat)m_InputSampleFormat); if (bIsPlanar) { char* pPackedData = (char*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); planarToInterleaved(pPackedData, pDecodedFrame, m_pStream->codec->channels, framesDecoded); pBuffer = resampleAudio(pPackedData, framesDecoded, av_get_packed_sample_fmt((AVSampleFormat)m_InputSampleFormat)); av_free(pPackedData); bNeedsResample = false; } #endif if (bNeedsResample) { pBuffer = resampleAudio(pDecodedData, framesDecoded, m_InputSampleFormat); } else if (!bIsPlanar) { pBuffer = AudioBufferPtr(new AudioBuffer(framesDecoded, m_AP)); memcpy(pBuffer->getData(), pDecodedData, bytesDecoded); } m_LastFrameTime += float(pBuffer->getNumFrames())/m_AP.m_SampleRate; pushAudioMsg(pBuffer, m_LastFrameTime); } } #if LIBAVCODEC_VERSION_MAJOR > 53 avcodec_free_frame(&pDecodedFrame); delete pDecodedFrame; #endif delete pTempPacket; }
SCM make_ffmpeg_output(SCM scm_file_name, SCM scm_format_name, SCM scm_video_parameters, SCM scm_have_video, SCM scm_audio_parameters, SCM scm_have_audio, SCM scm_debug) { SCM retval; struct ffmpeg_t *self; scm_dynwind_begin(0); const char *file_name = scm_to_locale_string(scm_file_name); scm_dynwind_free(file_name); self = (struct ffmpeg_t *)scm_gc_calloc(sizeof(struct ffmpeg_t), "ffmpeg"); self->video_stream_idx = -1; self->audio_stream_idx = -1; SCM_NEWSMOB(retval, ffmpeg_tag, self); int err; const char *format_name = NULL; if (!scm_is_false(scm_format_name)) { format_name = scm_to_locale_string(scm_symbol_to_string(scm_format_name)); scm_dynwind_free(format_name); }; #ifdef HAVE_AVFORMAT_ALLOC_OUTPUT_CONTEXT2 err = avformat_alloc_output_context2(&self->fmt_ctx, NULL, format_name, file_name); if (!self->fmt_ctx) { ffmpeg_destroy(retval); scm_misc_error("make-ffmpeg-output", "Error initializing output format for file '~a': ~a", scm_list_2(scm_file_name, get_error_text(err))); }; #else AVOutputFormat *format; if (format_name) format = av_guess_format(format_name, NULL, NULL); else format = av_guess_format(NULL, file_name, NULL); if (!format) { ffmpeg_destroy(retval); scm_misc_error("make-ffmpeg-output", "Unable to determine file format for file '~a'", scm_list_1(scm_file_name)); }; self->fmt_ctx = avformat_alloc_context(); if (!self->fmt_ctx) { ffmpeg_destroy(retval); scm_misc_error("make-ffmpeg-output", "Error initializing output format for file '~a'", scm_list_1(scm_file_name)); }; self->fmt_ctx->oformat = format; strncpy(self->fmt_ctx->filename, file_name, sizeof(self->fmt_ctx->filename)); #endif char have_video = scm_is_true(scm_have_video); if (have_video) { // Open codec and video stream enum AVCodecID video_codec_id = self->fmt_ctx->oformat->video_codec; AVCodec *video_encoder = find_encoder(retval, video_codec_id, "video"); AVStream *video_stream = open_output_stream(retval, video_encoder, &self->video_stream_idx, "video", scm_file_name); // Get video parameters SCM scm_shape = scm_car(scm_video_parameters); SCM scm_frame_rate = scm_cadr(scm_video_parameters); SCM scm_video_bit_rate = scm_caddr(scm_video_parameters); SCM scm_aspect_ratio = scm_cadddr(scm_video_parameters); // Configure the output video codec self->video_codec_ctx = configure_output_video_codec(video_stream, video_codec_id, scm_video_bit_rate, scm_shape, scm_frame_rate, scm_aspect_ratio); // Some formats want stream headers to be separate. if (self->fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) self->video_codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; // Open output video codec open_codec(retval, self->video_codec_ctx, video_encoder, "video", scm_file_name); // Allocate frame self->video_target_frame = allocate_output_video_frame(retval, self->video_codec_ctx); }; char have_audio = scm_is_true(scm_have_audio); if (have_audio) { // Open audio codec and stream enum AVCodecID audio_codec_id = self->fmt_ctx->oformat->audio_codec; AVCodec *audio_encoder = find_encoder(retval, audio_codec_id, "audio"); AVStream *audio_stream = open_output_stream(retval, audio_encoder, &self->audio_stream_idx, "audio", scm_file_name); // Get audio parameters SCM scm_select_rate = scm_car(scm_audio_parameters); SCM scm_channels = scm_cadr(scm_audio_parameters); SCM scm_audio_bit_rate = scm_caddr(scm_audio_parameters); SCM scm_select_format = scm_cadddr(scm_audio_parameters); // Configure the output audio codec self->audio_codec_ctx = configure_output_audio_codec(retval, audio_stream, audio_codec_id, scm_select_rate, scm_channels, scm_audio_bit_rate, scm_select_format); // Some formats want stream headers to be separate. if (self->fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) self->audio_codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; // Open output audio codec open_codec(retval, self->audio_codec_ctx, audio_encoder, "audio", scm_file_name); // Allocate audio frame self->audio_target_frame = allocate_output_audio_frame(retval, self->audio_codec_ctx, self->audio_codec_ctx->sample_fmt); self->audio_packed_frame = allocate_output_audio_frame(retval, self->audio_codec_ctx, av_get_packed_sample_fmt(self->audio_codec_ctx->sample_fmt)); // Initialise audio buffer ringbuffer_init(&self->audio_buffer, 1024); }; if (scm_is_true(scm_debug)) av_dump_format(self->fmt_ctx, 0, file_name, 1); // Open the output file if needed if (!(self->fmt_ctx->oformat->flags & AVFMT_NOFILE)) { int err = avio_open(&self->fmt_ctx->pb, file_name, AVIO_FLAG_WRITE); if (err < 0) { ffmpeg_destroy(retval); scm_misc_error("make-ffmpeg-output", "Could not open '~a': ~a", scm_list_2(scm_file_name, get_error_text(err))); } self->output_file = 1; } // Write video file header err = avformat_write_header(self->fmt_ctx, NULL); if (err < 0) { ffmpeg_destroy(retval); scm_misc_error("make-ffmpeg-output", "Error writing header of video '~a': ~a", scm_list_2(scm_file_name, get_error_text(err))); }; self->header_written = 1; scm_dynwind_end(); return retval; }