Uporaba vfw

Vse o večpredstavnosti (zvok, video, DirectShow in podobno).
Odgovori
sax15
Prispevkov: 88
Pridružen: 14.07.2003 10:27:40

Uporaba vfw

Odgovor Napisal/-a sax15 » 02.04.2014 15:22:32

Zdravo.
Imam težave z uporabo vfw.pas in sicer bi rad združil dva avi videa skupaj. Tmy_AVI_Tool Class ima nareje takole:

Koda: Izberi vse

uses ..., vfw;
...
type
  Tmy_AVI_Tool=Class
  private
    { Private declarations }
    m_IsPlaying: Boolean;
    m_File: PAVIFile;
    m_FileName: string;     
    m_PlayerHWND: HWND;
  public
   { Public declarations }
   m_Stream: PAVIStream;
   constructor Create(datoteka: String);
   destructor Destroy();override;
   function LoadAVI():Boolean;
   procedure Merge(parent: HWND; stream1, stream2: PAVIStream);
  published
   { Published declarations }
  end;

implementation

constructor Tmy_AVI_Tool.Create(datoteka: String);
begin
  m_IsPlaying:=False;
  m_Stream:=nil;
  m_FileName:=datoteka;
end;

destructor Tmy_AVI_Tool.Destroy();
begin
  if (m_Stream<>nil) then
  begin
    AVIStreamRelease(m_Stream);
    m_Stream:=nil;
  end;
  inherited Destroy;
end;

function Tmy_AVI_Tool.LoadAVI():Boolean;
begin
  // odpri AVi datoteko
  new(m_Stream);
  if (AVIFIleOpen(m_File, Pchar(m_FileName), OF_READ or OF_WRITE,nil)<>0) then
  begin
    if (AVIFILEGetStream(m_File, m_Stream, streamtypeVIDEO, 0)=AVIERR_NODATA) then
      Result:=False;
  end else
  begin
    // nisem uspel odpreti AVI datoteke
    AVIFileRelease(m_File);
    Result:=false;
  end;
end;

procedure Tmy_AVI_Tool.Merge(parent: HWND; stream1, stream2: PAVIStream);
var
  p: PAVIStream;
  dolp, dolp2: DWORD;
  dol, dol2: Longint;
  startp2: DWORD;
  start2: Longint;
begin
  new(p);
  if(CreateEditableStream(p, stream1)=0) then
  begin
    dolp:=AVIStreamLength(p);
    dolp2:=AVIStreamLength(stream2);
    startp2:=AVIStreamStart(stream2);
    if (EditStreamPaste(p, @dolp, @dolp2, stream2, start2, 0)<>0) then
    begin
	MessageBox(parent,'Združevanje AVI-jev ni uspelo!', 'Napaka pri združevanju!', MB_ICONERROR);
        exit;
    end;
  end;
end;
Potem pa iz Main form kličem takole:

Koda: Izberi vse

procedure TForm1.Button2Click(Sender: TObject);
var
    AVI1: Tmy_AVI_Tool;
    AVI2: Tmy_AVI_Tool;
    MergedAVI: Tmy_AVI_Tool;
    datoteka: String;
begin
    datoteka:='d:\video1.avi';
    AVI1:=Tmy_AVI_Tool.Create(datoteka);
    AVI1.LoadAVI();
    datoteka:='d:\video2.avi';
    AVI2:=Tmy_AVI_Tool.Create(datoteka);
    AVI2.LoadAVI();
    datoteka:='d:\merged.avi';
    MergedAVI:=Tmy_AVI_Tool.Create(datoteka);
    MergedAVI.Merge(Self.ClientHandle, AVI1.m_Stream, AVI2.m_Stream);
end;
Se pravi, za vsak video ustvarim objekt Tmy_AVI_Tool in mu naložim video z LoadAVI(), ki odpre datoteko in priredi kazalcu m_Stream naslov video streama

Koda: Izberi vse

function    AVIFileGetStream(pfile: PAVIFILE; var ppavi: PAVISTREAM; fccType: DWORD; lParam: DWORD): HResult; stdcall;
Težava je pri klicanju procedure Merge in sicer pri CreateEditableStream(p, stream1)

Koda: Izberi vse

function    CreateEditableStream(var ppsEditable: PAVISTREAM; psSource: PAVISTREAM): HResult; stdcall;
, kjer mi sporoči napako:
Project AVI.exe raised exception class EAccessViolation with message 'Access violation at address 70E30292 in module 'AVIFIL32.DLL'. Read of address 0000000C'., čeprav ima stram1 nek naslov (npr $16D50B0).

Očitno je nekaj narobe pri prenosu parametrov stream1 in stream2, pa ne vem kaj?

Help Please.

lp SaX

sax15
Prispevkov: 88
Pridružen: 14.07.2003 10:27:40

Re: Uporaba vfw

Odgovor Napisal/-a sax15 » 04.04.2014 08:22:24

OK, sem našel problem :(
Težava je bila v funkciji LoadAVI in sicer pri stavku

Koda: Izberi vse

if (AVIFIleOpen(m_File, Pchar(m_FileName), OF_READ or OF_WRITE,nil)[b]<>0[/b]) then
, ki vrne 0 v primeru, da se je AviFileOpen pravilno izvedel.
Pravilno je:

Koda: Izberi vse

function Tmy_AVI_Tool.LoadAVI():Boolean;
begin
  // odpri AVi datoteko
  new(m_Stream);
  if (AVIFIleOpen(m_File, Pchar(m_FileName), OF_READ or OF_WRITE,nil)=0) then
  begin
    if (AVIFILEGetStream(m_File, m_Stream, streamtypeVIDEO, 0)=AVIERR_NODATA) then
      Result:=False;
  end else
  begin
    // nisem uspel odpreti AVI datoteke
    AVIFileRelease(m_File);
    Result:=false;
  end;
end;
saj v nasportnem primeru se ne izvede AVIFILEGetStream in kazalec m_Stream kaže na neko prazno lokacijo.

Odgovori