Действительно, с рапидшары пропал пример для декодирования мр3; поправлю положение, показав еще раз – как использовать библиотеки от ffmpeg для декодирования звукового файла и последующего его кодирования в мр3
Правда я не разбирался никогда с созданием файлов, с наскоку не получилось – поэтому я пишу только мр3 – потому что у файла там структуры никакой – просто фреймы подряд (ну это если тегов нет)
Короче, вот код; не идеальный ни разу, цель то не в этом; а так – работает; пример представляет из себя 2 поля для ввода имени входного и выходного файлов, и кнопки “ДуИт”, обработчик клика которой собственно дальше:
var mp3_in: PAVFormatContext; decoder: PAVCodec; decoder_ctx: PAVCodecContext; encoder: PAVCodec; encoder_ctx: PAVCodecContext; pkt: TAVPacket; samples: PWord; buf: pointer; fp, nb, ret1, ret2: integer; fs: TFileStream; begin av_register_all; // регистрация форматов, кодеков etc try // читаем любые аудиофайлы: mp3_in := avformat_alloc_context; av_open_input_file(mp3_in, pansichar(ansistring(edMP3from.Text)), nil, 0, nil); av_find_stream_info(mp3_in); // но имеем в виду, что это аудиофайл, так что внутри ожидаем только один поток if mp3_in.streams [0].codec.codec_type <> CODEC_TYPE_AUDIO then raise Exception.Create('wrong file'); decoder_ctx := mp3_in.streams[0].codec; // ищем декодер decoder := avcodec_find_decoder(decoder_ctx.codec_id); if decoder = nil then raise Exception.Create('decoder not found'); // если нашли - инициализируем if avcodec_open(decoder_ctx, decoder) < 0 then raise Exception.Create('decoder error'); // хотим сделать мр3 с теми же параметрами, что и во входном файле, но с битрейтом 192 кбпс encoder_ctx := avcodec_alloc_context; encoder_ctx.codec_type := CODEC_TYPE_AUDIO; encoder_ctx.codec_id := CODEC_ID_MP3; encoder_ctx.channels := decoder_ctx.channels; encoder_ctx.sample_rate := decoder_ctx.sample_rate; encoder_ctx.bit_rate := 192000; encoder := avcodec_find_encoder(encoder_ctx.codec_id); if encoder = nil then raise Exception.Create('encoder not found'); // ищем кодек и инициализируем если есть (а его может и не быть, смотря как ffmpeg собран) if avcodec_open(encoder_ctx, encoder) < 0 then raise Exception.Create('encoder error'); // поскоку не умею писать файлы ffmpeg-ом, пишу просто все как есть в файл // для мр3 (ТОЛЬКО!) прокатит fs := TFileStream.Create(edMP3to.Text, fmCreate); samples := av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); buf := av_malloc(10000); // ну сколько не жалко и логично while av_read_frame(mp3_in, @pkt) >= 0 do begin // пока из вх. файла что-то читается - читаем; для видео пакеты будут из разных потоков (видео/звук) // но в моем идеальном примере поток только один nb := pkt.size; // что дальше: считан пакет размером ххх; но не факт, что декодер при распаковке // сразу использует все ххх байт - поэтому надо проверять while nb > 0 do begin fp := AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE ; // неочевидная фишка - перед каждым вызовом надо указать в fp размер буфера, куда распаковываем ret1 := avcodec_decode_audio2(decoder_ctx, samples, @fp, pkt.data, pkt.size); if ret1 < 0 then raise Exception.Create('decoding error'); // после decode в fp - размер данных декодированных; сделаем из них мр3 if fp > 0 then begin // я не знаю, как эта функция определяет, сколько данных надо взять из samples // (где лежит раскодированный звук) // но как-то оно работает.. ret2 := avcodec_encode_audio (encoder_ctx, buf, 10000, samples); if ret2 < 0 then raise Exception.Create('encoding error'); // если нет ошибки при кодировании - пишу закодированный звук в файл fs.Write(buf^, ret2); end; dec (nb, ret1); end; // ну собственно повторять до окончания файла.. av_free_packet(@pkt); end; finally av_free(buf); fs.Free; avcodec_close(encoder_ctx); av_free(encoder_ctx); av_free(samples); avcodec_close(decoder_ctx); av_close_input_file(mp3_in); av_free(mp3_in); end; end;
Надо посмотреть, все ли я ресурсы освободил, я в примерах с этим часто не заморачиваюсь; но суть должна быть понятна..
Проверял на dll-ках, собранных из ffmpeg 0.5.2, работает
Спасибо =) Только не все mp3 прочитывает...
ОтветитьУдалитьнапример? я особо не тестил, один файл прогнал и все - но работать должно в принципе
ОтветитьУдалитьпример в студию короче..