Действительно, с рапидшары пропал пример для декодирования мр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 прочитывает...
ОтветитьУдалитьнапример? я особо не тестил, один файл прогнал и все - но работать должно в принципе
ОтветитьУдалитьпример в студию короче..