Autor Beitrag
Flamefire
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: Mi 03.11.10 21:17 
Ich möchte MP3-Dateien (bzw Stücke davon) mit Nellymoser Codec transkodieren. Also, dass ein Teil der Datei mir mit Nellymoser Codec codiert im Speicher vorliegt.
Jetzt gibt es da aber diverse Probleme mit dem Codec, so dass ich keinen transcoder o.ä. gefunden habe.
Kennt jemand eine DLL o.ä. womit ich von MP3 auf Nellymoser komme?
Wie wird das dann gemacht?
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Mi 03.11.10 21:42 
Laut Wikipedia kann das FFMpeg. Hast du das schon probiert?

_________________
We are, we were and will not be.
Flamefire Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: Di 09.11.10 20:00 
Ok folgendes habe ich jetzt:
Ich habe aus einem RTMP Stream, der Mikrofondaten im Nellymoser Format mit 44,1kHz übeträgt, genau die Audiodaten extrahiert (ohne den RTMP header). Waren jeweils Chunks von 513 Byte (seltsamerweise 513...aber ok)
Dann wollte ich das mit FFMpeg decodieren lassen. Also alles in eine Datei geschrieben, und folgende Funktion geschrieben, woran ich das übergebe:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
procedure convert(const sFile,sOutFile:string);
var pCodec:PAVCodec;
    pCodecCtx:PAVCodecContext;
    outBuf:Array[0..AVCODEC_MAX_AUDIO_FRAME_SIZE-1of Byte;
    inBuf:Array[0..FF_INPUT_BUFFER_PADDING_SIZE+InBuf_Size-1of Byte;
    stIn,stOut:TStream;
    size,len,outSize:Integer;
    pInBuf:PByte;
begin
  pCodec:=avcodec_find_decoder(CODEC_ID_NELLYMOSER);
  if(pCodec=nilthen begin
    showmessage('no codec');
    exit;
  end;
  pCodecCtx:=avcodec_alloc_context();
  if(pCodecCtx=nilthen begin
    showmessage('no codecCtx');
    exit;
  end;
  if(avcodec_open(pCodecCtx,pCodec)<0then begin
    showmessage('Error open codec');
    exit;
  end;
  stIn:=TFileStream.Create(sFile,fmOpenRead);
  stIn.Position:=0;
  stOut:=TFileStream.Create(sOutFile,fmCreate);
  try
  while(stIn.Position<stIn.Size) do begin
    size:=stIn.Read(inBuf[0],InBuf_Size);
    pInBuf:=@inBuf[0];
    while(size>0do begin
      outSize:=Length(outBuf);
      len:=avcodec_decode_audio2(pCodecCtx,@outBuf[0],@outSize,pInBuf,size);
      if(len<=0then begin
        showmessage('Error decoding');
        exit;
      end;
      if(outSize>0then begin
        stOut.Write(outBuf[0],outSize);
      end;
      Dec(size,len);
      Inc(pInBuf,len);
    end;
  end;
  finally
    stIn.Free;
    stOut.Free;
    avcodec_close(pCodecCtx);
  end;
end;


Mit nem InBuf_Size von 513 (oder vielfache davon) läuft der durch (len=513). Sonst gibts Fehler oder Zugriffsverletzungen in der DLL. Das Problem: outSize ist immer 0. D.h. er gibt mir keine Ausgabe.
Weiß da jemand was?

Edit: Anscheinend werden die Daten gepuffert.
Hab beim testweise encode festgestellt, dass erstmal viele Daten in den Encoder reingehn und erst nach ein paar Sample-folgen AusgabeDaten kommen. Kann man den zwingen, auszugeben, was er bisher hat?

Edit2: Doch nicht (lt Source code) zumindest nicht beim decode.
Er braucht 512 Bytes sonst steigt er vorher aus.
Die AV kommt aus der DLL. s: ffmpeg.arrozcru.org/...mp;t=1603&p=5442
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Do 11.11.10 08:36 
Was passiert, wenn Du die Samples mit passendem Alignment von 16 Bytes an den Codec übergibst?

Um einen Pointer auf 16 Bytes zu alignen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
var P_Anywhere: Pointer;
    P_Align16: Pointer;
const AlignSize = 16;

P_Align16 := Pointer((AlignSize - 1 + Integer(P_Anywhere)) and not (AlignSize - 1));


Für AlignSize in (1 shl N) with N >= 0.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.