implementation(size_t output_channels, size_t input_channels, size_t output_sample_rate, size_t input_sample_rate, AVSampleFormat output_sample_format, AVSampleFormat input_sample_format) : output_channels_(output_channels) , output_sample_format_(output_sample_format) , input_channels_(input_channels) , input_sample_format_(input_sample_format) { if(input_channels != output_channels || input_sample_rate != output_sample_rate || input_sample_format != output_sample_format) { auto resampler = av_audio_resample_init(output_channels, input_channels, output_sample_rate, input_sample_rate, output_sample_format, input_sample_format, 16, 10, 0, 0.8); buffer2_.resize(AVCODEC_MAX_AUDIO_FRAME_SIZE*2); char sample_fmt_string[200]; av_get_sample_fmt_string(sample_fmt_string, 200, input_sample_format); CASPAR_LOG(warning) << L"[audio-resampler]" << L" sample-rate: " << input_sample_rate << L" channels: " << input_channels << L" sample-fmt: " << widen(sample_fmt_string); if(resampler) resampler_.reset(resampler, audio_resample_close); else BOOST_THROW_EXCEPTION(caspar_exception()); } }
static gboolean gst_ffmpegaudioresample_set_caps (GstBaseTransform * trans, GstCaps * incaps, GstCaps * outcaps) { GstFFMpegAudioResample *resample = GST_FFMPEGAUDIORESAMPLE (trans); GstStructure *instructure = gst_caps_get_structure (incaps, 0); GstStructure *outstructure = gst_caps_get_structure (outcaps, 0); GST_LOG_OBJECT (resample, "incaps:%" GST_PTR_FORMAT, incaps); GST_LOG_OBJECT (resample, "outcaps:%" GST_PTR_FORMAT, outcaps); if (!gst_structure_get_int (instructure, "channels", &resample->in_channels)) return FALSE; if (!gst_structure_get_int (instructure, "rate", &resample->in_rate)) return FALSE; if (!gst_structure_get_int (outstructure, "channels", &resample->out_channels)) return FALSE; if (!gst_structure_get_int (outstructure, "rate", &resample->out_rate)) return FALSE; /* FIXME : Allow configuring the various resampling properties */ #define TAPS 16 resample->res = av_audio_resample_init (resample->out_channels, resample->in_channels, resample->out_rate, resample->in_rate, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16, TAPS, 10, 0, 0.8); if (resample->res == NULL) return FALSE; return TRUE; }
FFwrapper::AudioResampler::AudioResampler(int in_ch, int in_rate, enum SampleFormat in_fmt, int out_ch, int out_rate) : buf(NULL), buf_size(0), ctx(NULL) { ctx = av_audio_resample_init( out_ch, in_ch, out_rate, in_rate, /* in, out parameters */ SAMPLE_FMT_S16, in_fmt, /* output, input formats */ 16, 10, 0, 0.8 /* filter length, log2 phase count, linear?, cutoff */ ); if (!ctx) { throw AllocationError("audio resampling context"); } }
AudioBufferPtr AudioDecoderThread::resampleAudio(char* pDecodedData, int framesDecoded, int currentSampleFormat) { if (!m_pResampleContext) { #ifdef LIBAVRESAMPLE_VERSION m_pResampleContext = avresample_alloc_context(); av_opt_set_int(m_pResampleContext, "in_channel_layout", av_get_default_channel_layout(m_pStream->codec->channels), 0); av_opt_set_int(m_pResampleContext, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); av_opt_set_int(m_pResampleContext, "in_sample_rate", m_InputSampleRate, 0); av_opt_set_int(m_pResampleContext, "out_sample_rate", m_AP.m_SampleRate, 0); av_opt_set_int(m_pResampleContext, "in_sample_fmt", (AVSampleFormat)currentSampleFormat, 0); av_opt_set_int(m_pResampleContext, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); int err = avresample_open(m_pResampleContext); AVG_ASSERT(err >= 0); #else m_pResampleContext = av_audio_resample_init(m_AP.m_Channels, m_pStream->codec->channels, m_AP.m_SampleRate, m_InputSampleRate, AV_SAMPLE_FMT_S16, (AVSampleFormat)currentSampleFormat, 16, 10, 0, 0.8); #endif AVG_ASSERT(m_pResampleContext); } #ifdef LIBAVRESAMPLE_VERSION uint8_t *pResampledData; int leftoverSamples = avresample_available(m_pResampleContext); int framesAvailable = leftoverSamples + av_rescale_rnd(avresample_get_delay(m_pResampleContext) + framesDecoded, m_AP.m_SampleRate, m_InputSampleRate, AV_ROUND_UP); av_samples_alloc(&pResampledData, 0, 2, framesAvailable, AV_SAMPLE_FMT_S16, 0); int framesResampled = avresample_convert(m_pResampleContext, &pResampledData, 0, framesAvailable, (uint8_t**)&pDecodedData, 0, framesDecoded); AudioBufferPtr pBuffer(new AudioBuffer(framesResampled, m_AP)); memcpy(pBuffer->getData(), pResampledData, framesResampled*m_AP.m_Channels*sizeof(short)); av_freep(&pResampledData); #else short pResampledData[AVCODEC_MAX_AUDIO_FRAME_SIZE/2]; int framesResampled = audio_resample(m_pResampleContext, pResampledData, (short*)pDecodedData, framesDecoded); AudioBufferPtr pBuffer(new AudioBuffer(framesResampled, m_AP)); memcpy(pBuffer->getData(), pResampledData, framesResampled*m_AP.m_Channels*sizeof(short)); #endif return pBuffer; }
int av_aud_init(char *file) { int i; AVDictionary *opts = NULL; av_register_all(); if(avformat_open_input(&pAFormatCtx, file, NULL, &opts)!=0) return -1; if (av_find_stream_info(pAFormatCtx)<0) return -1; audioStream=-1; for (i=0; i<pAFormatCtx->nb_streams; i++) if (pAFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO) { audioStream=i; break; } if (audioStream==-1) return -1; pACodecCtx=pAFormatCtx->streams[audioStream]->codec; pACodec=avcodec_find_decoder(pACodecCtx->codec_id); if (pACodec==NULL) return -1; if (avcodec_open(pACodecCtx, pACodec)<0) return -1; resampler = av_audio_resample_init(2, pACodecCtx->channels, 48000, pACodecCtx->sample_rate, AV_SAMPLE_FMT_FLT, pACodecCtx->sample_fmt, 16, 10, 0, 0.8); if (!resampler) return -1; buffered_samples = 0; return 0; }
bool AudioResamplerFfmpeg::init(AVCodecContext* ctx) { if ((ctx->sample_rate != 44100) || #if defined(HAVE_SWRESAMPLE_H) || defined(HAVE_AVRESAMPLE_H) (ctx->sample_fmt != AV_SAMPLE_FMT_S16) || #endif (ctx->channels != 2)) { if (! _context) { #ifdef HAVE_SWRESAMPLE_H _context = swr_alloc(); #elif HAVE_AVRESAMPLE_H _context = avresample_alloc_context(); #else _context = av_audio_resample_init(2, ctx->channels, 44100, ctx->sample_rate, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16, 16, 10, 0, 0.8); #endif #if defined(HAVE_SWRESAMPLE_H) || defined(HAVE_AVRESAMPLE_H) av_opt_set_int(_context, "in_channel_layout", av_get_default_channel_layout(ctx->channels), 0); av_opt_set_int(_context, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); av_opt_set_int(_context, "in_sample_rate", ctx->sample_rate, 0); av_opt_set_int(_context, "out_sample_rate", 44100, 0); av_opt_set_int(_context, "in_sample_fmt", ctx->sample_fmt, 0); av_opt_set_int(_context, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); #endif #ifdef HAVE_SWRESAMPLE_H swr_init(_context); #elif HAVE_AVRESAMPLE_H avresample_open(_context); #endif } return true; } return false; }
KeyFinder::AudioData* LibAvDecoder::decodeFile(const QString& filePath, const int maxDuration){ QMutexLocker codecMutexLocker(&codecMutex); // mutex the preparatory section of this method AVCodec *codec = NULL; AVFormatContext *fCtx = NULL; AVCodecContext *cCtx = NULL; AVDictionary* dict = NULL; // convert filepath #ifdef Q_OS_WIN const wchar_t* filePathWc = reinterpret_cast<const wchar_t*>(filePath.constData()); const char* filePathCh = utf16_to_utf8(filePathWc); #else QByteArray encodedPath = QFile::encodeName(filePath); const char* filePathCh = encodedPath; #endif // open file int openInputResult = avformat_open_input(&fCtx, filePathCh, NULL, NULL); if(openInputResult != 0){ throw KeyFinder::Exception(GuiStrings::getInstance()->libavCouldNotOpenFile(openInputResult).toLocal8Bit().constData()); } if(avformat_find_stream_info(fCtx, NULL) < 0){ av_close_input_file(fCtx); throw KeyFinder::Exception(GuiStrings::getInstance()->libavCouldNotFindStreamInformation().toLocal8Bit().constData()); } int audioStream = -1; for(int i=0; i<(signed)fCtx->nb_streams; i++){ if(fCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO){ audioStream = i; break; } } if(audioStream == -1){ av_close_input_file(fCtx); throw KeyFinder::Exception(GuiStrings::getInstance()->libavCouldNotFindAudioStream().toLocal8Bit().constData()); } // Determine duration int durationSeconds = fCtx->duration / AV_TIME_BASE; int durationMinutes = durationSeconds / 60; // First condition is a hack for bizarre overestimation of some MP3s if(durationMinutes < 720 && durationSeconds > maxDuration * 60){ av_close_input_file(fCtx); throw KeyFinder::Exception(GuiStrings::getInstance()->durationExceedsPreference(durationMinutes, durationSeconds % 60, maxDuration).toLocal8Bit().constData()); } // Determine stream codec cCtx = fCtx->streams[audioStream]->codec; codec = avcodec_find_decoder(cCtx->codec_id); if(codec == NULL){ av_close_input_file(fCtx); throw KeyFinder::Exception(GuiStrings::getInstance()->libavUnsupportedCodec().toLocal8Bit().constData()); } // Open codec int codecOpenResult = avcodec_open2(cCtx, codec, &dict); if(codecOpenResult < 0){ av_close_input_file(fCtx); throw KeyFinder::Exception(GuiStrings::getInstance()->libavCouldNotOpenCodec(codec->long_name, codecOpenResult).toLocal8Bit().constData()); } ReSampleContext* rsCtx = av_audio_resample_init( cCtx->channels, cCtx->channels, cCtx->sample_rate, cCtx->sample_rate, AV_SAMPLE_FMT_S16, cCtx->sample_fmt, 0, 0, 0, 0); if(rsCtx == NULL){ avcodec_close(cCtx); av_close_input_file(fCtx); throw KeyFinder::Exception(GuiStrings::getInstance()->libavCouldNotCreateResampleContext().toLocal8Bit().constData()); } qDebug("Decoding %s (%s, %d)", filePathCh, av_get_sample_fmt_name(cCtx->sample_fmt), cCtx->sample_rate); codecMutexLocker.unlock(); // Prep buffer KeyFinder::AudioData *audio = new KeyFinder::AudioData(); audio->setFrameRate(cCtx->sample_rate); audio->setChannels(cCtx->channels); // Decode stream AVPacket avpkt; int badPacketCount = 0; int badPacketThreshold = 100; while(true){ av_init_packet(&avpkt); if(av_read_frame(fCtx, &avpkt) < 0) break; if(avpkt.stream_index == audioStream){ try{ int result = decodePacket(cCtx, rsCtx, &avpkt, audio); if(result != 0){ if(badPacketCount < badPacketThreshold){ badPacketCount++; }else{ avcodec_close(cCtx); av_close_input_file(fCtx); throw KeyFinder::Exception(GuiStrings::getInstance()->libavTooManyBadPackets(badPacketThreshold).toLocal8Bit().constData()); } } }catch(KeyFinder::Exception& e){ throw e; } } av_free_packet(&avpkt); } codecMutexLocker.relock(); audio_resample_close(rsCtx); int codecCloseResult = avcodec_close(cCtx); if(codecCloseResult < 0){ qCritical("Error closing audio codec: %s (%d)", codec->long_name, codecCloseResult); } codecMutexLocker.unlock(); av_close_input_file(fCtx); return audio; }
KeyFinder::AudioData* LibAvDecoder::decodeFile(const QString& filePath){ QMutexLocker codecMutexLocker(&codecMutex); // mutex the preparatory section of this method AVCodec *codec = NULL; AVFormatContext *fCtx = NULL; AVCodecContext *cCtx = NULL; AVDictionary* dict = NULL; // convert filepath #ifdef Q_OS_WIN const wchar_t* filePathWc = reinterpret_cast<const wchar_t*>(filePath.constData()); const char* filePathCh = utf16_to_utf8(filePathWc); #else QByteArray encodedPath = QFile::encodeName(filePath); const char* filePathCh = encodedPath; #endif // open file int openInputResult = avformat_open_input(&fCtx, filePathCh, NULL, NULL); if(openInputResult != 0){ std::ostringstream ss; ss << "Could not open audio file (" << openInputResult << ")"; throw KeyFinder::Exception(ss.str()); } if(avformat_find_stream_info(fCtx,NULL) < 0){ throw KeyFinder::Exception("Could not find stream information"); } int audioStream = -1; for(int i=0; i<(signed)fCtx->nb_streams; i++){ if(fCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO){ audioStream = i; break; } } if(audioStream == -1){ throw KeyFinder::Exception("Could not find an audio stream"); } // Determine stream codec cCtx = fCtx->streams[audioStream]->codec; codec = avcodec_find_decoder(cCtx->codec_id); if(codec == NULL){ throw KeyFinder::Exception("Audio stream has unsupported codec"); } // Open codec int codecOpenResult = avcodec_open2(cCtx, codec, &dict); if(codecOpenResult < 0){ std::ostringstream ss; ss << "Could not open audio codec: " << codec->long_name << " (" << codecOpenResult << ")"; throw KeyFinder::Exception(ss.str()); } ReSampleContext* rsCtx = av_audio_resample_init( cCtx->channels, cCtx->channels, cCtx->sample_rate, cCtx->sample_rate, AV_SAMPLE_FMT_S16, cCtx->sample_fmt, 0, 0, 0, 0); if(rsCtx == NULL){ throw KeyFinder::Exception("Could not create ReSampleContext"); } qDebug("Decoding %s (%s, %d)", filePathCh, av_get_sample_fmt_name(cCtx->sample_fmt), cCtx->sample_rate); codecMutexLocker.unlock(); // Prep buffer KeyFinder::AudioData *audio = new KeyFinder::AudioData(); audio->setFrameRate(cCtx->sample_rate); audio->setChannels(cCtx->channels); // Decode stream AVPacket avpkt; int badPacketCount = 0; while(true){ av_init_packet(&avpkt); if(av_read_frame(fCtx, &avpkt) < 0) break; if(avpkt.stream_index == audioStream){ try{ int result = decodePacket(cCtx, rsCtx, &avpkt, audio); if(result != 0){ if(badPacketCount < 100){ badPacketCount++; }else{ throw KeyFinder::Exception("100 bad packets"); } } }catch(KeyFinder::Exception& e){ throw e; } } av_free_packet(&avpkt); } codecMutexLocker.relock(); audio_resample_close(rsCtx); int codecCloseResult = avcodec_close(cCtx); if(codecCloseResult < 0){ qCritical("Error closing audio codec: %s (%d)", codec->long_name, codecCloseResult); } codecMutexLocker.unlock(); av_close_input_file(fCtx); return audio; }
int AudioConvertFunc(const char *outfilename,int sample_rate,int channels,int sec,const char *inputfilename,HWND mParentHwnd,UINT mMsg) { AVCodec *aCodec =NULL; AVPacket *packet = NULL; AVFormatContext *pFormatCtx =NULL; AVCodecContext *aCodecCtx= NULL; ReSampleContext* ResampleCtx=NULL; AVFrame *decoded_frame = NULL; int datasize; //int tempcount = 0; //long total_out_size=0; int64_t total_in_convert_size = 0; int audioConvertProgress = 0; int tempAudioConvertProgress; unsigned int i; int len, ret, buffer_size, count, audio_stream_index = -1, totle_samplenum = 0; FILE *outfile = NULL;// *infile; head_pama pt; int16_t *audio_buffer = NULL; int16_t *resamplebuff = NULL; int ResampleChange=0; int ChannelsChange=0; int tempret; packet = (AVPacket*)malloc(sizeof(AVPacket)); if (packet==NULL) { PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)(-1)); return -1; } packet->data=NULL; buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE * 100; audio_buffer = (int16_t *)av_malloc(buffer_size); if (audio_buffer==NULL) { if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)(-2)); return -2; } av_register_all(); av_init_packet(packet); #if 0 /**********尝试分解av_open_input_file函数*************/ int ret = 0; AVFormatParameters ap = { 0 }; AVDictionary *tmp = NULL; AVInputFormat *fmt = NULL; AVDictionary **options = NULL; if (!pFormatCtx && !(pFormatCtx = avformat_alloc_context())) return AVERROR(ENOMEM); if (fmt) pFormatCtx->iformat = fmt; if (options) av_dict_copy(&tmp, *options, 0); if ((ret = av_opt_set_dict(pFormatCtx, &tmp)) < 0) goto fail; AVDictionary *tmp = NULL; if (!pFormatCtx && !(pFormatCtx = avformat_alloc_context())) return AVERROR(ENOMEM); int ret; AVProbeData pd = {inputfilename, NULL, 0}; if (pFormatCtx->pb) { pFormatCtx->flags |= AVFMT_FLAG_CUSTOM_IO; if (!pFormatCtx->iformat) return av_probe_input_buffer(pFormatCtx->pb, &pFormatCtx->iformat, inputfilename, pFormatCtx, 0, 0); else if (pFormatCtx->iformat->flags & AVFMT_NOFILE) av_log(pFormatCtx, AV_LOG_WARNING, "Custom AVIOContext makes no sense and " "will be ignored with AVFMT_NOFILE format.\n"); return 0; } if ( (pFormatCtx->iformat && pFormatCtx->iformat->flags & AVFMT_NOFILE) || (!pFormatCtx->iformat && (pFormatCtx->iformat = av_probe_input_format(&pd, 0)))) return 0; URLContext *h; int err; err = ffurl_open(&h, inputfilename, AVIO_RDONLY); if (err < 0) return err; err = ffio_fdopen(pFormatCtx, h); if (err < 0) { ffurl_close(h); return err; } if (pFormatCtx->iformat) return 0; av_probe_input_buffer(pFormatCtx->pb, &pFormatCtx->iformat, inputfilename, pFormatCtx, 0, 0); if (pFormatCtx->iformat->flags & AVFMT_NEEDNUMBER) { if (!av_filename_number_test(inputfilename)) { ret = AVERROR(EINVAL); goto fail; } } pFormatCtx->duration = pFormatCtx->start_time = AV_NOPTS_VALUE; av_strlcpy(pFormatCtx->filename, inputfilename ? inputfilename : "", sizeof(pFormatCtx->filename)); /* allocate private data */ if (pFormatCtx->iformat->priv_data_size > 0) { if (!(pFormatCtx->priv_data = av_mallocz(pFormatCtx->iformat->priv_data_size))) { ret = AVERROR(ENOMEM); goto fail; } if (pFormatCtx->iformat->priv_class) { *(const AVClass**)pFormatCtx->priv_data = pFormatCtx->iformat->priv_class; av_opt_set_defaults(pFormatCtx->priv_data); if ((ret = av_opt_set_dict(pFormatCtx->priv_data, &tmp)) < 0) goto fail; } } /* e.g. AVFMT_NOFILE formats will not have a AVIOContext */ if (pFormatCtx->pb) ff_id3v2_read(pFormatCtx, ID3v2_DEFAULT_MAGIC); if (!(pFormatCtx->flags&AVFMT_FLAG_PRIV_OPT) && pFormatCtx->iformat->read_header) if ((ret = pFormatCtx->iformat->read_header(pFormatCtx, &ap)) < 0) goto fail; if (!(pFormatCtx->flags&AVFMT_FLAG_PRIV_OPT) && pFormatCtx->pb && !pFormatCtx->data_offset) pFormatCtx->data_offset = avio_tell(pFormatCtx->pb); pFormatCtx->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; if (options) { av_dict_free(options); *options = tmp; } return 0; fail: av_dict_free(&tmp); if (pFormatCtx->pb && !(pFormatCtx->flags & AVFMT_FLAG_CUSTOM_IO)) avio_close(pFormatCtx->pb); avformat_free_context(pFormatCtx); pFormatCtx = NULL; return ret; return err; /**********尝试分解av_open_input_file函数*************/ //pFormatCtx = avformat_alloc_context(); #endif ret = av_open_input_file(&pFormatCtx, inputfilename, NULL,0, NULL); if(ret < 0) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)1); return 1; } ret = av_find_stream_info(pFormatCtx); if( ret < 0) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)2); return 2; } audio_stream_index=-1; for(i=0; i< (signed)pFormatCtx->nb_streams; i++) { if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO && audio_stream_index < 0) { audio_stream_index = i; break; } } if(audio_stream_index == -1) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)3); return 3; } aCodecCtx = pFormatCtx->streams[audio_stream_index]->codec; if (aCodecCtx==NULL) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)4); return 4; } aCodec = avcodec_find_decoder(aCodecCtx->codec_id); if(!aCodec) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } /*if (aCodecCtx!=NULL) { avcodec_close(aCodecCtx); aCodecCtx=NULL; }*/ PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)5); return 5; } //resample init if (channels==0) { channels=aCodecCtx->channels; } if (sample_rate==0) { sample_rate=aCodecCtx->sample_rate; } //if (aCodecCtx->channels!=channels) //{ // ChannelsChange=1; // ResampleChange=1; //} if (aCodecCtx->sample_rate!=sample_rate||aCodecCtx->channels!=channels) { ResampleChange=1; } if (ResampleChange==1) { ResampleCtx = av_audio_resample_init(channels,aCodecCtx->channels,sample_rate,aCodecCtx->sample_rate,SAMPLE_FMT_S16,SAMPLE_FMT_S16,16,10,0,1.0); if (ResampleCtx==NULL) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } /*if (aCodecCtx!=NULL) { avcodec_close(aCodecCtx); aCodecCtx=NULL; }*/ ResampleChange=0; PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)6); return 6; } resamplebuff=(int16_t *)malloc(buffer_size); if (resamplebuff==NULL) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } /*if (aCodecCtx!=NULL) { avcodec_close(aCodecCtx); aCodecCtx=NULL; }*/ if (ResampleChange==1&&ResampleCtx!=NULL) { audio_resample_close(ResampleCtx); ResampleCtx=NULL; } PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)7); return 7; } } // datasize=sec*sample_rate; if(avcodec_open(aCodecCtx, aCodec)<0) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } if (aCodecCtx!=NULL) { avcodec_close(aCodecCtx); aCodecCtx=NULL; } if (ResampleChange==1&&ResampleCtx!=NULL&&resamplebuff!=NULL) { audio_resample_close(ResampleCtx); ResampleCtx=NULL; free(resamplebuff); resamplebuff=NULL; } ResampleChange=0; PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)8); return 8; } pt.bits = 16; pt.channels = channels; pt.rate = sample_rate; outfile = fopen(outfilename, "wb"); if (!outfile) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } if (aCodecCtx!=NULL) { avcodec_close(aCodecCtx); aCodecCtx=NULL; } if (ResampleChange==1&&ResampleCtx!=NULL&&resamplebuff!=NULL) { audio_resample_close(ResampleCtx); ResampleCtx=NULL; free(resamplebuff); resamplebuff=NULL; } ResampleChange=0; PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)9); return 9; } fseek(outfile,44,SEEK_SET); while(av_read_frame(pFormatCtx, packet) >= 0) { CheckMessageQueue(); if(packet->stream_index == audio_stream_index) { //while(packet->size > 0) //{ buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE * 100; len = avcodec_decode_audio3(aCodecCtx, audio_buffer, &buffer_size, packet); if (len < 0) { break; } if(buffer_size > 0) { //resample if (ResampleChange==1) { int samples=buffer_size/ ((aCodecCtx->channels) * 2); int resamplenum= 0; resamplenum = audio_resample(ResampleCtx, resamplebuff, audio_buffer, samples); count = fwrite(resamplebuff, 2*channels, resamplenum, outfile); } else { count = fwrite(audio_buffer, 2*aCodecCtx->channels, buffer_size/((aCodecCtx->channels)*2), outfile); } totle_samplenum += count; } //tempcount++; //total_out_size += count*2*aCodecCtx->channels; total_in_convert_size += packet->size; tempAudioConvertProgress = 100*total_in_convert_size/(pFormatCtx->file_size); if(tempAudioConvertProgress != audioConvertProgress) { if(tempAudioConvertProgress == 100) tempAudioConvertProgress = 99; audioConvertProgress = tempAudioConvertProgress; tempret = PostMessage(mParentHwnd,mMsg,DECING_TAG,audioConvertProgress); } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } //packet->size -= len; //packet->data += len; //} if (datasize!=0&&totle_samplenum>=datasize) { break; } } } audioConvertProgress = 100; PostMessage(mParentHwnd,mMsg,DECING_TAG,audioConvertProgress); fseek(outfile,0,SEEK_SET); wav_write_header(outfile, pt, totle_samplenum); if (outfile!=NULL) { fclose(outfile); outfile=NULL; } if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (aCodecCtx!=NULL) { avcodec_close(aCodecCtx); aCodecCtx=NULL; } if (packet!=NULL) { free(packet);// packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } if (ResampleChange==1) { if (resamplebuff!=NULL) { free(resamplebuff); resamplebuff=NULL; } if (ResampleCtx!=NULL) { audio_resample_close(ResampleCtx); ResampleCtx=NULL; } } if (totle_samplenum<=sample_rate*5) { PostMessage(mParentHwnd,mMsg,FAILED_TAG,(LPARAM)10); return 10; } PostMessage(mParentHwnd,mMsg,FINISH_TAG,NULL); return 0; }
int AudioConvertFunc_Buffer(const short *pcmbuffer,int sample_rate,int channels,int sec,const char *inputfilename,int *pcmbuff_size) { AVCodec *aCodec =NULL; AVPacket *packet = NULL; AVFormatContext *pFormatCtx =NULL; AVCodecContext *aCodecCtx= NULL; ReSampleContext* ResampleCtx=NULL; AVFrame *decoded_frame = NULL; int datasize; unsigned int i; int len, ret, buffer_size, audio_stream_index = -1, totle_samplenum = 0; ////1.FILE *outfile = NULL;// *infile; head_pama pt; int16_t *audio_buffer = NULL; int16_t *resamplebuff = NULL; int ResampleChange=0; int ChannelsChange=0; int totalsize=0; packet = (AVPacket*)malloc(sizeof(AVPacket)); if (packet==NULL) { return -1; } packet->data=NULL; buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE * 100; audio_buffer = (int16_t *)av_malloc(buffer_size); if (audio_buffer==NULL) { if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } return -2; } av_register_all(); av_init_packet(packet); //pFormatCtx = avformat_alloc_context(); ret = av_open_input_file(&pFormatCtx, inputfilename, NULL,0, NULL); if(ret < 0) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } return 1; } ret = av_find_stream_info(pFormatCtx); if( ret < 0) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } return 2; } audio_stream_index=-1; for(i=0; i< (signed)pFormatCtx->nb_streams; i++) { if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO && audio_stream_index < 0) { audio_stream_index = i; break; } } if(audio_stream_index == -1) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } return 3; } aCodecCtx = pFormatCtx->streams[audio_stream_index]->codec; if (aCodecCtx==NULL) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } return 4; } aCodec = avcodec_find_decoder(aCodecCtx->codec_id); if(!aCodec) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } /*if (aCodecCtx!=NULL) { avcodec_close(aCodecCtx); aCodecCtx=NULL; }*/ return 5; } //resample init if (channels==0) { channels=aCodecCtx->channels; } if (sample_rate==0) { sample_rate=aCodecCtx->sample_rate; } //if (aCodecCtx->channels!=channels) //{ // ChannelsChange=1; // ResampleChange=1; //} if (aCodecCtx->sample_rate!=sample_rate||aCodecCtx->channels!=channels) { ResampleChange=1; } if (ResampleChange==1) { ResampleCtx = av_audio_resample_init(channels,aCodecCtx->channels,sample_rate,aCodecCtx->sample_rate,SAMPLE_FMT_S16,SAMPLE_FMT_S16,16,10,0,1.0); if (ResampleCtx==NULL) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } /*if (aCodecCtx!=NULL) { avcodec_close(aCodecCtx); aCodecCtx=NULL; }*/ ResampleChange=0; return 6; } resamplebuff=(int16_t *)malloc(buffer_size); if (resamplebuff==NULL) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } /*if (aCodecCtx!=NULL) { avcodec_close(aCodecCtx); aCodecCtx=NULL; }*/ if (ResampleChange==1&&ResampleCtx!=NULL) { audio_resample_close(ResampleCtx); ResampleCtx=NULL; } return 7; } } // datasize=sec*sample_rate; if(avcodec_open(aCodecCtx, aCodec)<0) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } if (aCodecCtx!=NULL) { avcodec_close(aCodecCtx); aCodecCtx=NULL; } if (ResampleChange==1&&ResampleCtx!=NULL&&resamplebuff!=NULL) { audio_resample_close(ResampleCtx); ResampleCtx=NULL; free(resamplebuff); resamplebuff=NULL; } ResampleChange=0; return 8; } pt.bits = 16; pt.channels = channels; pt.rate = sample_rate; ////2.outfile = fopen(outfilename, "wb"); ////3.outfile pcmbuffer if (!pcmbuffer) { if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } if (packet!=NULL) { free(packet); packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } if (aCodecCtx!=NULL) { avcodec_close(aCodecCtx); aCodecCtx=NULL; } if (ResampleChange==1&&ResampleCtx!=NULL&&resamplebuff!=NULL) { audio_resample_close(ResampleCtx); ResampleCtx=NULL; free(resamplebuff); resamplebuff=NULL; } ResampleChange=0; return 9; } ////4.fseek(outfile,44,SEEK_SET); while(av_read_frame(pFormatCtx, packet) >= 0) { CheckMessageQueue(); if(packet->stream_index == audio_stream_index) { //while(packet->size > 0) //{ buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE * 100; len = avcodec_decode_audio3(aCodecCtx, audio_buffer, &buffer_size, packet); if (len < 0) { break; } if(buffer_size > 0) { //resample if (ResampleChange==1) { int samples=buffer_size/ ((aCodecCtx->channels) * 2); int resamplenum= 0; resamplenum = audio_resample(ResampleCtx, resamplebuff, audio_buffer, samples); ////5.count = fwrite(resamplebuff, 2*channels, resamplenum, outfile); memcpy((char*)(pcmbuffer+totalsize/2),resamplebuff,2*channels*resamplenum); totalsize+=2*channels*resamplenum; totle_samplenum+=resamplenum; } else { ////6.count = fwrite(audio_buffer, 2*aCodecCtx->channels, buffer_size/((aCodecCtx->channels)*2), outfile); memcpy((char*)(pcmbuffer+totalsize/2),audio_buffer,2*channels*buffer_size/((aCodecCtx->channels)*2)); totalsize+=2*channels*buffer_size/((aCodecCtx->channels)*2); totle_samplenum+=buffer_size/ ((aCodecCtx->channels) * 2); } ////totle_samplenum += count; if(totalsize>=2*channels*(sample_rate*sec)) { *pcmbuff_size=totalsize/2/channels; break; } } if (packet->data!=NULL) { av_free_packet(packet); packet->data=NULL; } //packet->size -= len; //packet->data += len; //} if (datasize!=0&&totle_samplenum>=datasize) { break; } } } if (audio_buffer!=NULL) { av_free(audio_buffer); audio_buffer=NULL; } if (aCodecCtx!=NULL) { avcodec_close(aCodecCtx); aCodecCtx=NULL; } if (packet!=NULL) { free(packet);// packet=NULL; } if (pFormatCtx!=NULL) { av_close_input_file(pFormatCtx); pFormatCtx=NULL; } if (ResampleChange==1) { if (resamplebuff!=NULL) { free(resamplebuff); resamplebuff=NULL; } if (ResampleCtx!=NULL) { audio_resample_close(ResampleCtx); ResampleCtx=NULL; } } if (totle_samplenum<=sample_rate*5) { return 10; } return 0; }
// Initialize resampler // // Generic // ::new(src_channels, src_rate, src_format, dst_format) - Change sample format // ::new(src_channels, src_rate, src_format, dst_rate, dst_format) - Change sample rate and format // ::new(src_channels, src_rate, src_format, dst_channels, dst_rate, dst_format) - Change channel count, sample rate, and format // // From Object // ::new(source, dst_format) - Change sample format // ::new(source, dst_rate, dst_format) - Change sample rate and format // ::new(source, dst_channels, dst_rate, dst_format) - Change channel count, sample rate, and format VALUE audio_resampler_initialize(int argc, VALUE * argv, VALUE self) { AudioResamplerInternal * internal; Data_Get_Struct(self, AudioResamplerInternal, internal); if (argc && TYPE(argv[0]) == T_FIXNUM) { // Called generic form if (argc < 4) rb_raise(rb_eArgError, "Missing argument(s)"); else if (argc > 6) rb_raise(rb_eArgError, "Too many arguments"); internal->src_channels = NUM2INT(argv[0]); internal->src_rate = NUM2INT(argv[1]); internal->src_format = symbol_to_av_sample_format(argv[2]); argc -= 3; argv += 3; } else { // Called with object if (argc < 2) rb_raise(rb_eArgError, "Missing argument(s)"); else if (argc > 4) rb_raise(rb_eArgError, "Too many arguments"); internal->src_channels = NUM2INT(rb_funcall(argv[0], rb_intern("channels"), 0)); internal->src_rate = NUM2INT(rb_funcall(argv[0], rb_intern("rate"), 0)); internal->src_format = symbol_to_av_sample_format(rb_funcall(argv[0], rb_intern("format"), 0)); argc -= 1; argv += 1; } internal->dst_channels = internal->src_channels; internal->dst_rate = internal->src_rate; internal->dst_format = internal->src_format; switch (argc) { case 1: { // Change sample format internal->dst_format = symbol_to_av_sample_format(argv[0]); break; } case 2: { // Change sample rate and format internal->dst_rate = NUM2INT(argv[0]); internal->dst_format = symbol_to_av_sample_format(argv[1]); break; } case 3: { // Change channel count, sample rate, and sampleformat internal->dst_channels = NUM2INT(argv[0]); internal->dst_rate = NUM2INT(argv[1]); internal->dst_format = symbol_to_av_sample_format(argv[2]); break; } } if (internal->src_format == AV_SAMPLE_FMT_NONE) rb_raise(rb_eArgError, "Unknown input sample format"); if (internal->dst_format == AV_SAMPLE_FMT_NONE) rb_raise(rb_eArgError, "Unknown output sample format"); // Create audio resampler internal->context = av_audio_resample_init(internal->dst_channels, internal->src_channels, internal->dst_rate, internal->src_rate, internal->dst_format, internal->src_format, 0, 0, 1, 0.0); if (!internal->context) rb_raise(rb_eRuntimeError, "Failed to create resampling context"); return self; }
static int resample_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples ) { // Get the filter service mlt_filter filter = mlt_frame_pop_audio( frame ); // Get the filter properties mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter ); mlt_service_lock( MLT_FILTER_SERVICE( filter ) ); // Get the resample information int output_rate = mlt_properties_get_int( filter_properties, "frequency" ); int16_t *sample_buffer = mlt_properties_get_data( filter_properties, "buffer", NULL ); // Obtain the resample context if it exists ReSampleContext *resample = mlt_properties_get_data( filter_properties, "audio_resample", NULL ); // If no resample frequency is specified, default to requested value if ( output_rate == 0 ) output_rate = *frequency; // Get the producer's audio int error = mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples ); if ( error ) return error; // Return now if no work to do if ( output_rate != *frequency ) { // Will store number of samples created int used = 0; mlt_log_debug( MLT_FILTER_SERVICE(filter), "channels %d samples %d frequency %d -> %d\n", *channels, *samples, *frequency, output_rate ); // Do not convert to s16 unless we need to change the rate if ( *format != mlt_audio_s16 ) { *format = mlt_audio_s16; mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples ); } // Create a resampler if nececessary if ( resample == NULL || *frequency != mlt_properties_get_int( filter_properties, "last_frequency" ) ) { // Create the resampler resample = av_audio_resample_init( *channels, *channels, output_rate, *frequency, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16, 16, 10, 0, 0.8 ); // And store it on properties mlt_properties_set_data( filter_properties, "audio_resample", resample, 0, ( mlt_destructor )audio_resample_close, NULL ); // And remember what it was created for mlt_properties_set_int( filter_properties, "last_frequency", *frequency ); } mlt_service_unlock( MLT_FILTER_SERVICE( filter ) ); // Resample the audio used = audio_resample( resample, sample_buffer, *buffer, *samples ); int size = used * *channels * sizeof( int16_t ); // Resize if necessary if ( used > *samples ) { *buffer = mlt_pool_realloc( *buffer, size ); mlt_frame_set_audio( frame, *buffer, *format, size, mlt_pool_release ); } // Copy samples memcpy( *buffer, sample_buffer, size ); // Update output variables *samples = used; *frequency = output_rate; } else { mlt_service_unlock( MLT_FILTER_SERVICE( filter ) ); } return error; }
int main(int argc, char* argv[]) { AVFormatContext* in_fctx; AVCodecContext* in_cctx; AVCodec* in_codec; const char* in_filename; const char* out_filename; char* decoded_buf; char* output_buf; char* resample_buf; char* before_encoding_buf; int ret = 0; if (argc != 3) { printf("./audio_convertor input ouput\n"); return -1; } //in_filename = "../input/input.aac"; //out_filename = "output/aac2mp3.mp3"; in_filename = argv[1]; out_filename = argv[2]; decoded_buf = (char*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); output_buf = (char*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); resample_buf = (char*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); before_encoding_buf = (char*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); avcodec_register_all(); av_register_all(); in_fctx = avformat_alloc_context(); ret = av_open_input_file(&in_fctx, in_filename, NULL, 0, NULL); if ( ret != 0 ) { printf("open input audio file[%s] fail\n", in_filename); return -1; } ret = av_find_stream_info(in_fctx); if ( ret < 0 ) { printf("find stream in audio file[%s] fail\n", in_filename); return -1; } dump_format(in_fctx, 0, in_filename, 0); //这里我们假设,如果一个文件包含多个音频流, //只对第一个音频流做转码,而对于视频流则忽略 int i; int ast_index = -1; for (i = 0; i<(int)in_fctx->nb_streams; ++i) { if (in_fctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { ast_index = i; break; } } if (ast_index == -1) { printf("there is not any audio stream in file[%s]\n", in_filename); return 0; } else { printf("find audio stream in file[%s]\n", in_filename); } in_cctx = in_fctx->streams[ast_index]->codec; //in_cctx->codec_id = CODEC_ID_GSM; in_codec = avcodec_find_decoder(in_cctx->codec_id); if (!in_codec) { printf("find decoder for codec_id[%d] fail, file[%s]\n", in_cctx->codec_id, in_filename); return -1; } ret = avcodec_open(in_cctx, in_codec); if (ret >= 0) { printf("open codec[name:%s] for stream[idx:%d] of file[%s]\n", in_codec->name, ast_index, in_filename); } // 输出部分初始化 AVOutputFormat* out_fmt; AVFormatContext* out_fctx; AVCodecContext* out_cctx = NULL; out_fmt = av_guess_format(NULL, out_filename, NULL); if (!out_fmt) { printf("Could not deduce output format from file extension: using MPEG-3.\n"); out_fmt = av_guess_format("mp3", NULL, NULL); } if (!out_fmt) { fprintf(stderr, "Could not find suitable output format\n"); exit(1); } out_fctx = avformat_alloc_context(); if (!out_fctx) { fprintf(stderr, "avformat_alloc_context fail\n"); exit(1); } out_fctx->oformat = out_fmt; out_cctx = output_decode_init(in_cctx, out_fctx, out_fmt->audio_codec); if (!out_cctx) { fprintf(stderr, "output_codec_init fail\n"); exit(1); } /* set the output parameters (must be done even if no parameters). */ if (av_set_parameters(out_fctx, NULL) < 0) { fprintf(stderr, "Invalid output format parameters\n"); exit(1); } dump_format(out_fctx, 0, out_filename, 1); output_decode_open(out_cctx); /* open the output file */ if (!(out_fmt->flags & AVFMT_NOFILE)) { if (url_fopen(&out_fctx->pb, out_filename, URL_WRONLY) < 0) { fprintf(stderr, "Could not open '%s'\n", out_filename); exit(1); } } /* write the stream header, if any */ if(av_write_header(out_fctx) < 0) { fprintf(stderr, "Could not write header for output file\n"); return -1; } int decoded_size; AVPacket in_packet; AVPacket out_packet; ReSampleContext *rs_ctx = NULL; /* 参考链接:http://hi.baidu.com/wg_wang/item/34396781d20b4b1ec316270b 两点需要注意: (1) 从输入文件中按帧读取数据,解码,按照输出文件的要求,编码,并按帧写入到输出文件中。 在这里,由于sample_rate和channels可能不同,需要对音频数据进行重采样。 (2) 由于不同编码类型对一帧音频的数据要求不同,可能需要将输入数据保存起来,直到够输出的编码使用, 或者,一帧的输入数据可能需要被多次输出。 这样,要求初始化重采样以及libavutil提供的fifo(libavutils/fifo.h声明)以临时保存数据。 举个例子:aac的frame_size=1024,mp3的frame_size=1152。若不用这个fifo,则生成的mp3文件是有问题的 */ // 设置从采样 rs_ctx = av_audio_resample_init( out_cctx->channels, in_cctx->channels, out_cctx->sample_rate, in_cctx->sample_rate, out_cctx->sample_fmt, in_cctx->sample_fmt, 16, 10, 0, 0.8); AVFifoBuffer *iofifo; iofifo = av_fifo_alloc(AVCODEC_MAX_AUDIO_FRAME_SIZE*2); av_init_packet(&in_packet); av_init_packet(&out_packet); while (av_read_frame(in_fctx, &in_packet) >= 0) { while (in_packet.size > 0) { int used_size; decoded_size = AVCODEC_MAX_AUDIO_FRAME_SIZE; used_size = avcodec_decode_audio3(in_cctx, (int16_t *)decoded_buf, &decoded_size, &in_packet); if (used_size < 0) { printf("avcodec_decode_audio3 fail\n"); exit(1); } int bs, frame_bytes; bs = audio_resample(rs_ctx, (short *)resample_buf, (short *)decoded_buf, decoded_size/(in_cctx->channels*g_in_bytes)); ret = av_fifo_generic_write(iofifo, (uint8_t *)resample_buf, bs*out_cctx->channels*g_out_bytes, NULL); //ret = av_fifo_generic_write(iofifo, (uint8_t *)decoded_buf, in_cctx->frame_size*in_cctx->channels*g_out_bytes, NULL); frame_bytes = out_cctx->frame_size * g_out_bytes * out_cctx->channels; while(av_fifo_size(iofifo) >= frame_bytes) { ret = av_fifo_generic_read(iofifo, before_encoding_buf, frame_bytes, NULL); out_packet.size = avcodec_encode_audio(out_cctx, (uint8_t*)output_buf, frame_bytes, (short *)before_encoding_buf); out_packet.data = (uint8_t *)output_buf; av_write_frame(out_fctx, &out_packet); } in_packet.size -= used_size; in_packet.data += used_size; } } /* write the trailer, if any */ av_write_trailer(out_fctx); if (!(out_fmt->flags & AVFMT_NOFILE)) { /* close the output file */ url_fclose(out_fctx->pb); } }
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 (av_open_input_file(&ctx->fmt_ctx, file, NULL, 0, NULL) != 0) { printf("Couldn't open input file %s\n", file); return -1; } if (av_find_stream_info(ctx->fmt_ctx) < 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) { return -1; printf("No audio codec\n"); } if (avcodec_open(ctx->a_codec_ctx, ctx->a_codec) < 0) { printf("Failed to open audio codec\n"); return -1; } printf("Audio srate: %d\n", ctx->a_codec_ctx->sample_rate); ctx->a_ch = 2; if (ctx->a_codec_ctx->channels > 2) ctx->a_ch = ctx->a_codec_ctx->channels; ctx->a_resampler = av_audio_resample_init(ctx->a_ch, ctx->a_codec_ctx->channels, SAMPLE_RATE, ctx->a_codec_ctx->sample_rate, SAMPLE_FMT_S16, ctx->a_codec_ctx->sample_fmt, 16, 10, 0, 0.8); if (!ctx->a_resampler) return -1; ctx->a_ratio = SAMPLE_RATE/(double)ctx->a_codec_ctx->sample_rate; ctx->a_stride = av_get_bits_per_sample_fmt(ctx->a_codec_ctx->sample_fmt) / 8; ctx->a_stride *= ctx->a_codec_ctx->channels; ctx->a_ibuf = malloc(ctx->a_stride * AVCODEC_MAX_AUDIO_FRAME_SIZE); ctx->a_rbuf = malloc(ctx->a_ch * sizeof(short) * AVCODEC_MAX_AUDIO_FRAME_SIZE * (ctx->a_ratio * 1.1)); ctx->a_buf_len = AUDIO_BUF*SAMPLE_RATE; ctx->a_buf = malloc(sizeof(*ctx->a_buf) * ctx->a_buf_len); 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_open(ctx->v_codec_ctx, ctx->v_codec) < 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_codec_ctx->get_buffer = hack_get_buffer; ctx->v_codec_ctx->release_buffer = hack_release_buffer; ctx->v_codec_ctx->opaque = ctx; ctx->v_frame = avcodec_alloc_frame(); 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; }