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

📄 api.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:

  if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
    return 0;

  return asiw.dwStart;
}

/***********************************************************************
 *		AVIStreamLength		(AVIFILE.131)
 *		AVIStreamLength		(AVIFIL32.@)
 */
LONG WINAPI AVIStreamLength(PAVISTREAM pstream)
{
  AVISTREAMINFOW asiw;

  TRACE("(%p)\n", pstream);

  if (pstream == NULL)
    return 0;

  if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
    return 0;

  return asiw.dwLength;
}

/***********************************************************************
 *		AVIStreamSampleToTime	(AVIFILE.133)
 *		AVIStreamSampleToTime	(AVIFIL32.@)
 */
LONG WINAPI AVIStreamSampleToTime(PAVISTREAM pstream, LONG lSample)
{
  AVISTREAMINFOW asiw;
  LONG time;

  TRACE("(%p,%d)\n", pstream, lSample);

  if (pstream == NULL)
    return -1;

  if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
    return -1;
  if (asiw.dwRate == 0)
    return -1;

  /* limit to stream bounds */
  if (lSample < asiw.dwStart)
    lSample = asiw.dwStart;
  if (lSample > asiw.dwStart + asiw.dwLength)
    lSample = asiw.dwStart + asiw.dwLength;

  if (asiw.dwRate / asiw.dwScale < 1000)
    time = (LONG)(((float)lSample * asiw.dwScale * 1000) / asiw.dwRate);
  else
    time = (LONG)(((float)lSample * asiw.dwScale * 1000 + (asiw.dwRate - 1)) / asiw.dwRate);

  TRACE(" -> %d\n",time);
  return time;
}

/***********************************************************************
 *		AVIStreamTimeToSample	(AVIFILE.132)
 *		AVIStreamTimeToSample	(AVIFIL32.@)
 */
LONG WINAPI AVIStreamTimeToSample(PAVISTREAM pstream, LONG lTime)
{
  AVISTREAMINFOW asiw;
  ULONG sample;

  TRACE("(%p,%d)\n", pstream, lTime);

  if (pstream == NULL || lTime < 0)
    return -1;

  if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
    return -1;
  if (asiw.dwScale == 0)
    return -1;

  if (asiw.dwRate / asiw.dwScale < 1000)
    sample = (LONG)((((float)asiw.dwRate * lTime) / (asiw.dwScale * 1000)));
  else
    sample = (LONG)(((float)asiw.dwRate * lTime + (asiw.dwScale * 1000 - 1)) / (asiw.dwScale * 1000));

  /* limit to stream bounds */
  if (sample < asiw.dwStart)
    sample = asiw.dwStart;
  if (sample > asiw.dwStart + asiw.dwLength)
    sample = asiw.dwStart + asiw.dwLength;

  TRACE(" -> %d\n", sample);
  return sample;
}

/***********************************************************************
 *		AVIBuildFilter		(AVIFIL32.@)
 *		AVIBuildFilterA		(AVIFIL32.@)
 *		AVIBuildFilter		(AVIFILE.123)
 */
HRESULT WINAPI AVIBuildFilterA(LPSTR szFilter, LONG cbFilter, BOOL fSaving)
{
  LPWSTR  wszFilter;
  HRESULT hr;

  TRACE("(%p,%d,%d)\n", szFilter, cbFilter, fSaving);

  /* check parameters */
  if (szFilter == NULL)
    return AVIERR_BADPARAM;
  if (cbFilter < 2)
    return AVIERR_BADSIZE;

  szFilter[0] = 0;
  szFilter[1] = 0;

  wszFilter = HeapAlloc(GetProcessHeap(), 0, cbFilter * sizeof(WCHAR));
  if (wszFilter == NULL)
    return AVIERR_MEMORY;

  hr = AVIBuildFilterW(wszFilter, cbFilter, fSaving);
  if (SUCCEEDED(hr)) {
    WideCharToMultiByte(CP_ACP, 0, wszFilter, cbFilter,
			szFilter, cbFilter, NULL, NULL);
  }

  HeapFree(GetProcessHeap(), 0, wszFilter);

  return hr;
}

/***********************************************************************
 *		AVIBuildFilterW		(AVIFIL32.@)
 */
HRESULT WINAPI AVIBuildFilterW(LPWSTR szFilter, LONG cbFilter, BOOL fSaving)
{
  static const WCHAR szClsid[] = {'C','L','S','I','D',0};
  static const WCHAR szExtensionFmt[] = {';','*','.','%','s',0};
  static const WCHAR szAVIFileExtensions[] =
    {'A','V','I','F','i','l','e','\\','E','x','t','e','n','s','i','o','n','s',0};

  AVIFilter *lp;
  WCHAR      szAllFiles[40];
  WCHAR      szFileExt[10];
  WCHAR      szValue[128];
  HKEY       hKey;
  DWORD      n, i;
  LONG       size;
  DWORD      count = 0;

  TRACE("(%p,%d,%d)\n", szFilter, cbFilter, fSaving);

  /* check parameters */
  if (szFilter == NULL)
    return AVIERR_BADPARAM;
  if (cbFilter < 2)
    return AVIERR_BADSIZE;

  lp = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_FILTERS * sizeof(AVIFilter));
  if (lp == NULL)
    return AVIERR_MEMORY;

  /*
   * 1. iterate over HKEY_CLASSES_ROOT\\AVIFile\\Extensions and collect
   *    extensions and CLSID's
   * 2. iterate over collected CLSID's and copy its description and its
   *    extensions to szFilter if it fits
   *
   * First filter is named "All multimedia files" and its filter is a
   * collection of all possible extensions except "*.*".
   */
  if (RegOpenKeyW(HKEY_CLASSES_ROOT, szAVIFileExtensions, &hKey) != S_OK) {
    HeapFree(GetProcessHeap(), 0, lp);
    return AVIERR_ERROR;
  }
  for (n = 0;RegEnumKeyW(hKey, n, szFileExt, sizeof(szFileExt)) == S_OK;n++) {
    /* get CLSID to extension */
    size = sizeof(szValue)/sizeof(szValue[0]);
    if (RegQueryValueW(hKey, szFileExt, szValue, &size) != S_OK)
      break;

    /* search if the CLSID is already known */
    for (i = 1; i <= count; i++) {
      if (lstrcmpW(lp[i].szClsid, szValue) == 0)
	break; /* a new one */
    }

    if (count - i == -1U) {
      /* it's a new CLSID */

      /* FIXME: How do we get info's about read/write capabilities? */

      if (count >= MAX_FILTERS) {
	/* try to inform user of our full fixed size table */
	ERR(": More than %d filters found! Adjust MAX_FILTERS in dlls/avifil32/api.c\n", MAX_FILTERS);
	break;
      }

      lstrcpyW(lp[i].szClsid, szValue);

      count++;
    }

    /* append extension to the filter */
    wsprintfW(szValue, szExtensionFmt, szFileExt);
    if (lp[i].szExtensions[0] == 0)
      lstrcatW(lp[i].szExtensions, szValue + 1);
    else
      lstrcatW(lp[i].szExtensions, szValue);

    /* also append to the "all multimedia"-filter */
    if (lp[0].szExtensions[0] == 0)
      lstrcatW(lp[0].szExtensions, szValue + 1);
    else
      lstrcatW(lp[0].szExtensions, szValue);
  }
  RegCloseKey(hKey);

  /* 2. get descriptions for the CLSIDs and fill out szFilter */
  if (RegOpenKeyW(HKEY_CLASSES_ROOT, szClsid, &hKey) != S_OK) {
    HeapFree(GetProcessHeap(), 0, lp);
    return AVIERR_ERROR;
  }
  for (n = 0; n <= count; n++) {
    /* first the description */
    if (n != 0) {
      size = sizeof(szValue)/sizeof(szValue[0]);
      if (RegQueryValueW(hKey, lp[n].szClsid, szValue, &size) == S_OK) {
	size = lstrlenW(szValue);
	lstrcpynW(szFilter, szValue, cbFilter);
      }
    } else
      size = LoadStringW(AVIFILE_hModule,IDS_ALLMULTIMEDIA,szFilter,cbFilter);

    /* check for enough space */
    size++;
    if (cbFilter < size + lstrlenW(lp[n].szExtensions) + 2) {
      szFilter[0] = 0;
      szFilter[1] = 0;
      HeapFree(GetProcessHeap(), 0, lp);
      RegCloseKey(hKey);
      return AVIERR_BUFFERTOOSMALL;
    }
    cbFilter -= size;
    szFilter += size;

    /* and then the filter */
    lstrcpynW(szFilter, lp[n].szExtensions, cbFilter);
    size = lstrlenW(lp[n].szExtensions) + 1;
    cbFilter -= size;
    szFilter += size;
  }

  RegCloseKey(hKey);
  HeapFree(GetProcessHeap(), 0, lp);

  /* add "All files" "*.*" filter if enough space left */
  size = LoadStringW(AVIFILE_hModule, IDS_ALLFILES,
		     szAllFiles, sizeof(szAllFiles)) + 1;
  if (cbFilter > size) {
    int i;

    /* replace '@' with \000 to separate description of filter */
    for (i = 0; i < size && szAllFiles[i] != 0; i++) {
      if (szAllFiles[i] == '@') {
	szAllFiles[i] = 0;
	break;
      }
    }
      
    memcpy(szFilter, szAllFiles, size * sizeof(szAllFiles[0]));
    szFilter += size;
    szFilter[0] = 0;

    return AVIERR_OK;
  } else {
    szFilter[0] = 0;
    return AVIERR_BUFFERTOOSMALL;
  }
}

static BOOL AVISaveOptionsFmtChoose(HWND hWnd)
{
  LPAVICOMPRESSOPTIONS pOptions = SaveOpts.ppOptions[SaveOpts.nCurrent];
  AVISTREAMINFOW       sInfo;

  TRACE("(%p)\n", hWnd);

  if (pOptions == NULL || SaveOpts.ppavis[SaveOpts.nCurrent] == NULL) {
    ERR(": bad state!\n");
    return FALSE;
  }

  if (FAILED(AVIStreamInfoW(SaveOpts.ppavis[SaveOpts.nCurrent],
			    &sInfo, sizeof(sInfo)))) {
    ERR(": AVIStreamInfoW failed!\n");
    return FALSE;
  }

  if (sInfo.fccType == streamtypeVIDEO) {
    COMPVARS cv;
    BOOL     ret;

    memset(&cv, 0, sizeof(cv));

    if ((pOptions->dwFlags & AVICOMPRESSF_VALID) == 0) {
      memset(pOptions, 0, sizeof(AVICOMPRESSOPTIONS));
      pOptions->fccType    = streamtypeVIDEO;
      pOptions->fccHandler = comptypeDIB;
      pOptions->dwQuality  = (DWORD)ICQUALITY_DEFAULT;
    }

    cv.cbSize     = sizeof(cv);
    cv.dwFlags    = ICMF_COMPVARS_VALID;
    /*cv.fccType    = pOptions->fccType; */
    cv.fccHandler = pOptions->fccHandler;
    cv.lQ         = pOptions->dwQuality;
    cv.lpState    = pOptions->lpParms;
    cv.cbState    = pOptions->cbParms;
    if (pOptions->dwFlags & AVICOMPRESSF_KEYFRAMES)
      cv.lKey = pOptions->dwKeyFrameEvery;
    else
      cv.lKey = 0;
    if (pOptions->dwFlags & AVICOMPRESSF_DATARATE)
      cv.lDataRate = pOptions->dwBytesPerSecond / 1024; /* need kBytes */
    else
      cv.lDataRate = 0;

    ret = ICCompressorChoose(hWnd, SaveOpts.uFlags, NULL,
			     SaveOpts.ppavis[SaveOpts.nCurrent], &cv, NULL);

    if (ret) {
      pOptions->fccHandler = cv.fccHandler;
      pOptions->lpParms   = cv.lpState;
      pOptions->cbParms   = cv.cbState;
      pOptions->dwQuality = cv.lQ;
      if (cv.lKey != 0) {
	pOptions->dwKeyFrameEvery = cv.lKey;
	pOptions->dwFlags |= AVICOMPRESSF_KEYFRAMES;
      } else
	pOptions->dwFlags &= ~AVICOMPRESSF_KEYFRAMES;
      if (cv.lDataRate != 0) {
	pOptions->dwBytesPerSecond = cv.lDataRate * 1024; /* need bytes */
	pOptions->dwFlags |= AVICOMPRESSF_DATARATE;
      } else
	pOptions->dwFlags &= ~AVICOMPRESSF_DATARATE;
      pOptions->dwFlags  |= AVICOMPRESSF_VALID;
    }
    ICCompressorFree(&cv);

    return ret;
  } else if (sInfo.fccType == streamtypeAUDIO) {
    ACMFORMATCHOOSEW afmtc;
    MMRESULT         ret;
    LONG             size;

    /* FIXME: check ACM version -- Which version is needed? */

    memset(&afmtc, 0, sizeof(afmtc));
    afmtc.cbStruct  = sizeof(afmtc);
    afmtc.fdwStyle  = 0;
    afmtc.hwndOwner = hWnd;

    acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, &size);
    if ((pOptions->cbFormat == 0 || pOptions->lpFormat == NULL) && size != 0) {
      pOptions->lpFormat = HeapAlloc(GetProcessHeap(), 0, size);
      pOptions->cbFormat = size;
    } else if (pOptions->cbFormat < (DWORD)size) {
      pOptions->lpFormat = HeapReAlloc(GetProcessHeap(), 0, pOptions->lpFormat, size);
      pOptions->cbFormat = size;
    }
    if (pOptions->lpFormat == NULL)
      return FALSE;
    afmtc.pwfx  = pOptions->lpFormat;
    afmtc.cbwfx = pOptions->cbFormat;

    size = 0;
    AVIStreamFormatSize(SaveOpts.ppavis[SaveOpts.nCurrent],
			sInfo.dwStart, &size);
    if (size < (LONG)sizeof(PCMWAVEFORMAT))
      size = sizeof(PCMWAVEFORMAT);
    afmtc.pwfxEnum = HeapAlloc(GetProcessHeap(), 0, size);
    if (afmtc.pwfxEnum != NULL) {
      AVIStreamReadFormat(SaveOpts.ppavis[SaveOpts.nCurrent],
			  sInfo.dwStart, afmtc.pwfxEnum, &size);
      afmtc.fdwEnum = ACM_FORMATENUMF_CONVERT;
    }

    ret = acmFormatChooseW(&afmtc);
    if (ret == S_OK)
      pOptions->dwFlags |= AVICOMPRESSF_VALID;

    HeapFree(GetProcessHeap(), 0, afmtc.pwfxEnum);
    return (ret == S_OK ? TRUE : FALSE);
  } else {
    ERR(": unknown streamtype 0x%08X\n", sInfo.fccType);
    return FALSE;
  }
}

static void AVISaveOptionsUpdate(HWND hWnd)
{
  static const WCHAR szVideoFmt[]={'%','l','d','x','%','l','d','x','%','d',0};
  static const WCHAR szAudioFmt[]={'%','s',' ','%','s',0};

  WCHAR          szFormat[128];
  AVISTREAMINFOW sInfo;
  LPVOID         lpFormat;
  LONG           size;

  TRACE("(%p)\n", hWnd);

  SaveOpts.nCurrent = SendDlgItemMessageW(hWnd,IDC_STREAM,CB_GETCURSEL,0,0);
  if (SaveOpts.nCurrent < 0)
    return;

  if (FAILED(AVIStreamInfoW(SaveOpts.ppavis[SaveOpts.nCurrent], &sInfo, sizeof(sInfo))))
    return;

  AVIStreamFormatSize(SaveOpts.ppavis[SaveOpts.nCurrent],sInfo.dwStart,&size);
  if (size > 0) {
    szFormat[0] = 0;

    /* read format to build format description string */
    lpFormat = HeapAlloc(GetProcessHeap(), 0, size);
    if (lpFormat != NULL) {
      if (SUCCEEDED(AVIStreamReadFormat(SaveOpts.ppavis[SaveOpts.nCurrent],sInfo.dwStart,lpFormat, &size))) {
	if (sInfo.fccType == streamtypeVIDEO) {
	  LPBITMAPINFOHEADER lpbi = lpFormat;
	  ICINFO icinfo;

	  wsprintfW(szFormat, szVideoFmt, lpbi->biWidth,
		    lpbi->biHeight, lpbi->biBitCount);

	  if (lpbi->biCompression != BI_RGB) {
	    HIC    hic;

	    hic = ICLocate(ICTYPE_VIDEO, sInfo.fccHandler, lpFormat,
			   NULL, ICMODE_DECOMPRESS);
	    if (hic != NULL) {
	      if (ICGetInfo(hic, &icinfo, sizeof(icinfo)) == S_OK)
		lstrcatW(szFormat, icinfo.szDescription);
	      ICClose(hic);
	    }
	  } else {
	    LoadStringW(AVIFILE_hModule, IDS_UNCOMPRESSED,
			icinfo.szDescription, sizeof(icinfo.szDescription));
	    lstrcatW(szFormat, icinfo.szDescription);

⌨️ 快捷键说明

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