⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 source.cpp

📁 avisynth-source-0.3.zip,avi edit src
💻 CPP
📖 第 1 页 / 共 2 页
字号:
  IDirectDrawSurface* pDDSurface;
  IAudioMediaStream* pAudMStream;
  IAudioStreamSample* pAudSample;
  IAudioData* pAudData;

  BYTE* audioBuffer;

  int next_frame, first_audio_sample, next_audio_sample;

  VideoInfo vi;

//  frameLength;
//  totalTime;

  bool OpenVideo(const char* fileName);
  bool OpenAudio(const char* fileName);

public:
  DirectShowSource(const char* fileName);
  ~DirectShowSource();

  void GetFrame(int n, unsigned char* buf);
  void GetAudio(void* buf, int start, int count);
  void GetVideoInfo(VideoInfo* pvi);
  bool GetParity(int n);

  static PVideoFilter __cdecl Create(const FilterInfo*, const Arg* args, const char*) {
    return new DirectShowSource(args[0].string);
  }
};


void DirectShowSource::GetVideoInfo(VideoInfo* pvi) { *pvi = vi; }
bool DirectShowSource::GetParity(int n) { return false; }


DirectShowSource::DirectShowSource(const char* fileName) {
  pDD = NULL;
  pMMStream = NULL;
  pAudMMStream = NULL;
  pVidStream = NULL;
  pAudStream = NULL;
  pDDMStream = NULL;
  pDDSample = NULL;
  pDDSurface = NULL;
  pAudMStream = NULL;
  pAudSample = NULL;
  pAudData = NULL;
  audioBuffer = NULL;
  memset(&vi, 0, sizeof(VideoInfo));

  try {
    // need non-short-circuiting & here!
    if (!OpenVideo(fileName) & !OpenAudio(fileName))
      throw FilterChainError(Sprintf("DirectShowSource: Could not open %s", fileName));
    if (!vi.HasVideo() && !vi.HasAudio())
      throw FilterChainError(Sprintf("DirectShowSource: no video or audio stream found"));
  }
  catch (FilterChainError) {
    this->~DirectShowSource();
    throw;
  }

  next_frame = 0;
  first_audio_sample = 0;
  next_audio_sample = 0;
}


bool DirectShowSource::OpenVideo(const char* fileName) {

  WCHAR wPath[MAX_PATH];
  MultiByteToWideChar(CP_ACP, 0, fileName, -1, wPath, sizeof(wPath)/sizeof(wPath[0]));

  if (CoCreateInstance(CLSID_AMMultiMediaStream, NULL, CLSCTX_INPROC_SERVER,
                       IID_IAMMultiMediaStream, (void **)&pMMStream) != S_OK)
  {
    throw FilterChainError("DirectShowSource: Could not create AMMultiMediaStream (video)");
  }

  if (pMMStream->Initialize(STREAMTYPE_READ, 0, NULL) != S_OK)
    throw FilterChainError("DirectShowSource: Could not initialize AMMultiMediaStream (video)");

  if (pMMStream->AddMediaStream(NULL, &MSPID_PrimaryVideo, 0, NULL) != S_OK)
    throw FilterChainError("DirectShowSource: Could not add PrimaryVideo to AMMultiMediaStream");

  if (pMMStream->OpenFile(wPath, AMMSF_NOCLOCK) != S_OK)
    return false;

  if (pMMStream->GetMediaStream(MSPID_PrimaryVideo, &pVidStream) != S_OK)
    throw FilterChainError("DirectShowSource: Could not get PrimaryVideo");

  if (pVidStream->QueryInterface(IID_IDirectDrawMediaStream, (void **)&pDDMStream) != S_OK)
    throw FilterChainError("DirectShowSource: Could not get IDirectDrawMediaStream from PrimaryVideo");

  __int64 frameLength;
  if (pDDMStream->GetTimePerFrame(&frameLength) != S_OK)
    return true;
//    throw FilterChainError("DirectShowSource: Could not get time per frame from IDirectDrawStream");

  __int64 totalTime;
  if (pMMStream->GetDuration(&totalTime) != S_OK)
    throw FilterChainError("DirectShowSource: Could not get Duration from IMultiMediaStream (video)");

  vi.num_frames = long((totalTime+(frameLength>>1)) / frameLength);
  vi.fps_numerator = 10000000;
  vi.fps_denominator = int(frameLength);
  vi.field_based = false;

  DDSURFACEDESC ddsd;

  memset(&ddsd, 0, sizeof(ddsd));
  ddsd.dwSize = sizeof(ddsd);
  ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);

  if (pDDMStream->GetFormat(&ddsd, NULL, NULL, NULL) != S_OK)
    throw FilterChainError("DirectShowSource: Could not get video width and height");

  if (!(ddsd.dwFlags & DDSD_WIDTH) || !(ddsd.dwFlags & DDSD_HEIGHT))
    throw FilterChainError("DirectShowSource: Could not get video width and height 1");

  vi.width = ddsd.dwWidth;
  vi.height = ddsd.dwHeight;
  vi.pixel_type = VideoInfo::BGR24;

  memset(&ddsd, 0, sizeof(ddsd));
  ddsd.dwSize = sizeof(ddsd);
  ddsd.dwWidth = vi.width;
  ddsd.dwHeight = vi.height;
  ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
  ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
  ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
  ddsd.ddpfPixelFormat.dwRBitMask = 0x00FF0000;
  ddsd.ddpfPixelFormat.dwGBitMask = 0x0000FF00;
  ddsd.ddpfPixelFormat.dwBBitMask = 0x000000FF;
  ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
  ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;

  if (DirectDrawCreate(NULL, &pDD, NULL) != DD_OK)
    throw FilterChainError("DirectShowSource: Could not create a DirectDraw instance");

  if (pDD->SetCooperativeLevel(GetDesktopWindow(), DDSCL_NORMAL) != DD_OK)
    throw FilterChainError("DirectShowSource: Could not set the DirectDraw Cooperative level");

  if (pDD->CreateSurface(&ddsd, &pDDSurface, NULL) != DD_OK)
    throw FilterChainError("DirectShowSource: Could not create a DirectDraw surface");

  if (pDDMStream->SetDirectDraw(pDD) != S_OK)
    throw FilterChainError("DirectShowSource: Could not set the DirectDraw surface");

  if (pDDMStream->CreateSample(pDDSurface, NULL, 0, &pDDSample) != S_OK)
    throw FilterChainError("DirectShowSource: Could not create a DirectDraw sample");

  if (pMMStream->SetState(STREAMSTATE_RUN) != S_OK)
    throw FilterChainError("DirectShowSource: Could not start stream running (video)");

  return true;
}


bool DirectShowSource::OpenAudio(const char* fileName) {

  WCHAR wPath[MAX_PATH];
  MultiByteToWideChar(CP_ACP, 0, fileName, -1, wPath, sizeof(wPath)/sizeof(wPath[0]));

  if (CoCreateInstance(CLSID_AMMultiMediaStream, NULL, CLSCTX_INPROC_SERVER,
                       IID_IAMMultiMediaStream, (void **)&pAudMMStream) != S_OK)
  {
    throw FilterChainError("DirectShowSource: Could not create AMMultiMediaStream (audio)");
  }

  if (pAudMMStream->Initialize(STREAMTYPE_READ, 0, NULL) != S_OK)
    throw FilterChainError("DirectShowSource: Could not initialize AMMultiMediaStream (audio)");

  if (pAudMMStream->AddMediaStream(NULL, &MSPID_PrimaryAudio, 0, NULL) != S_OK)
    throw FilterChainError("DirectShowSource: Could not add PrimaryAudio to AMMultiMediaStream");

  if (pAudMMStream->OpenFile(wPath, AMMSF_NOCLOCK) != S_OK)
    return false;

  __int64 totalTime;
  if (pAudMMStream->GetDuration(&totalTime) != S_OK)
    throw FilterChainError("DirectShowSource: Could not get Duration from IMultiMediaStream");

  if (pAudMMStream->GetMediaStream(MSPID_PrimaryAudio, &pAudStream) != S_OK)
    throw FilterChainError("DirectShowSource: Could not get PrimaryAudio");

  if (pAudStream->QueryInterface(IID_IAudioMediaStream, (void**)&pAudMStream) != S_OK)
    throw FilterChainError("DirectShowSource: Could not get IAudioMediaStream from PrimaryAudio");

  WAVEFORMATEX audioFormat;

  if (pAudMStream->GetFormat(&audioFormat) != S_OK)
    return true;

  if (audioFormat.wFormatTag != WAVE_FORMAT_PCM)
    return true;	// other types not supported

  if (CoCreateInstance(CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER,
                       IID_IAudioData, (void **)&pAudData) != S_OK)
    return true;	// "Could not create IAudioData"

  vi.audio_samples_per_second = audioFormat.nSamplesPerSec;
  vi.num_audio_samples = int(totalTime / 10000000.0 * audioFormat.nSamplesPerSec);
  vi.stereo = (audioFormat.nChannels == 2);
  vi.sixteen_bit = (audioFormat.wBitsPerSample == 16);

  int audioBufferSize = vi.BytesFromAudioSamples(vi.audio_samples_per_second);

  audioBuffer = new BYTE[audioBufferSize];
  if (!audioBuffer)
    throw FilterChainError("DirectShowSource: Could not create an audio buffer");

  if (pAudData->SetBuffer(audioBufferSize, audioBuffer, 0) != S_OK)
    throw FilterChainError("DirectShowSource: Could not set the audio buffer in IAudioData");

  if (pAudData->SetFormat(&audioFormat) != S_OK)
    throw FilterChainError("DirectShowSource: Could not set the format in IAudioData");

  if (pAudMStream->CreateSample(pAudData, 0, &pAudSample) != S_OK)
    throw FilterChainError("DirectShowSource: Could not create IAudioStreamSample");

  if (pAudMMStream->SetState(STREAMSTATE_RUN) != S_OK)
    throw FilterChainError("DirectShowSource: Could not start stream running (audio)");

  return true;
}


void DirectShowSource::GetFrame(int n, unsigned char* buf) {

  n = min(max(n,0),vi.num_frames-1);

  if (n != next_frame) {
    // note: vi.fps_denominator happens to equal frame length in 10^-7 sec. units
    __int64 pos = n * __int64(vi.fps_denominator);
    if (pMMStream->Seek(pos) != S_OK)
      throw FilterChainError(Sprintf("DirectShowSource: Seek to %d failed", n));
  }

  next_frame=n+1;

  if (FAILED(pDDSample->Update(0, NULL, NULL, 0)))
    throw FilterChainError("DirectShowSource: DDSample::Update failed");

  DDSURFACEDESC ddsd;
  memset(&ddsd, 0, sizeof(ddsd));
  ddsd.dwSize = sizeof(ddsd);
  if (pDDSurface->Lock(NULL, &ddsd, 0, NULL) != DD_OK)
    throw FilterChainError("DirectShowSource: DDSurface::Lock failed");

  unsigned char* src = (unsigned char*)ddsd.lpSurface + vi.width*4*(vi.height-1);
  unsigned char* dst = buf;
  for (int y=vi.height; y; --y) {
    for (int x=0; x<vi.width; ++x) {
      dst[x*3+0] = src[x*4+0];
      dst[x*3+1] = src[x*4+1];
      dst[x*3+2] = src[x*4+2];
    }
    dst += vi.width*3;
    src -= vi.width*4;
  }

  if (pDDSurface->Unlock(NULL) != S_OK)
    throw FilterChainError("DirectShowSource: DDSurface::Unlock failed");
}


void DirectShowSource::GetAudio(void* buf, int start, int count) {

  count = vi.AudioSamplesFromBytes(count);

  if (start < 0) {
    int leading_zeroes = min(0-start, count);
    memset(buf, 0, vi.BytesFromAudioSamples(leading_zeroes));
    count -= leading_zeroes;
    start += leading_zeroes;
  }

  if (start+count > vi.num_audio_samples) {
    if (start >= vi.num_audio_samples) {
      memset(buf, 0, vi.BytesFromAudioSamples(count));
      return;
    } else {
      memset((char*)buf+vi.BytesFromAudioSamples(vi.num_audio_samples-start), 0, vi.BytesFromAudioSamples(start+count-vi.num_audio_samples));
      count = vi.num_audio_samples - start;
    }
  }

  while (count) {
    if (first_audio_sample <= start && next_audio_sample > start) {
      const int from = start;
      const int to = min(start+count, next_audio_sample);
      memcpy(buf, audioBuffer + vi.BytesFromAudioSamples(from-first_audio_sample), vi.BytesFromAudioSamples(to-from));
      buf = (char*)buf + vi.BytesFromAudioSamples(to-from);
      count -= to-from;
      start = to;
      if (!count) return;
    }

    if (start != next_audio_sample) {
      __int64 pos = start * 10000000i64 / vi.audio_samples_per_second;
      if (pAudMMStream->Seek(pos) != S_OK)
        throw FilterChainError("DirectShowSource: AudMMStream::Seek failed");
    }

    first_audio_sample = start;
    next_audio_sample = first_audio_sample + vi.audio_samples_per_second;

    if (FAILED(pAudSample->Update(0, NULL, NULL, 0)))
      throw FilterChainError("DirectShowSource: AudSample::Update failed");
  }
}


DirectShowSource::~DirectShowSource()
{
  if (pAudSample)  pAudSample->Release();
  if (pAudData)    pAudData->Release();
  if (pAudMStream) pAudMStream->Release();
  if (pAudStream)  pAudStream->Release();
  if (audioBuffer) delete[] audioBuffer;
  if (pAudMMStream)   pAudMMStream->Release();

  if (pDDSample)   pDDSample->Release();
  if (pDDSurface)  pDDSurface->Release();
  if (pDD)         pDD->Release();
  if (pDDMStream)  pDDMStream->Release();
  if (pVidStream)  pVidStream->Release();
  if (pMMStream)   pMMStream->Release();
}


/********************************************************************
********************************************************************/


PVideoFilter __cdecl Create_SegmentedAVISource(const FilterInfo*, const Arg* args, const char* arg_types) {
  PVideoFilter result = 0;

  for (int i = 0; arg_types[i]; ++i) {
    char basename[260];
    strcpy(basename, args[i].string);
    char* extension = strrchr(basename, '.');
    if (extension)
      *extension++ = 0;
    else
      extension = "";
    for (int j = 0; j < 100; ++j) {
      char filename[260];
      wsprintf(filename, "%s.%02d.%s", basename, j, extension);
      if (GetFileAttributes(filename) != (DWORD)-1) {   // check if file exists
        PVideoFilter clip = new AVISource(filename, 0);
        result = !result ? clip : new_Splice(false, result, clip);
      }
    }
  }
  if (!result)
    throw FilterChainError("SegmentedAVISource: no files found!");
  return result;
}


PVideoFilter __cdecl Create_Version(const FilterInfo*, const Arg*, const char*) {
  VideoInfo vi;
  memset(&vi, 0, sizeof(vi));
  vi.width = 512;
  vi.height = 32;
  vi.fps_denominator = 1;
  vi.fps_numerator = 15;
  vi.num_frames = 150;
  vi.pixel_type = VideoInfo::BGR24;
  return new_Subtitle("Avisynth v0.3, copyright 2000 Ben Rudiak-Gould", -1, 23, 0, 999, "Arial", 24, 0xFF8800, 0, new Blackness(&vi));
}


FilterInfo source_filters[] = {
  { "AVISource", "s", AVISource::Create },
  { "AVIFileSource", "s", AVISource::CreateAVIFile },
  { "WAVSource", "s", AVISource::CreateAVIFile },
  { "OpenDMLSource", "s", AVISource::CreateOpenDML },
  { "SegmentedAVISource", "s+", Create_SegmentedAVISource },
  { "IPCSource", "s", IPCSource::Create },
  { "DirectShowSource", "s", DirectShowSource::Create },
  { "Blackness", "ic", Blackness::Create },
  { "Version", "", Create_Version },
  { 0,0,0 }
};


PVideoFilter new_Blackness(VideoInfo* pvi) { return new Blackness(pvi); }
PVideoFilter new_Blackness(PVideoFilter pvf, int num_frames) { return new Blackness(pvf, num_frames); }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -