前言:

在CSDN上也耗了很久,但是每次都是看人家的文章或帖子,奉行的都是“拿来主义”,从来没有自己的文章发表,有了blog,我也有机会了,但是没有什么含金量的文章,也不知写哪方面的东西,前段时间在论坛上发了个帖子,主要是CD转WMA方面的,但是帖子很快就沉了,因为没有几个人知道。经过自己的努力,终于做出来了,鉴于很多人还不知道怎么作,所以斗胆在此乱发一通,希望高手还望见谅!

正文:

网上有CD to WAV的文章和源码。但wav和wma还是有很大不同,我是参考了怎样读CD信息的相关代码,然后自己实现了一个CCDAudioInput的类,该类封装了CD的信息和读取CD数据的相关操作。主要的难点是怎样把CD数据存入wma文件里,因为wma是Microsoft的asf文件格式,所以我看了Microsoft的windows media SDK和里面的samples。windows media SDK主要是以com组件实现的开发库,个人觉得只要大概了解com应该问题不大。为了方便Wma的操作我设计了一个CWmvWriter的类,里面包括了对wma文件的写入操作以及一些初始化工作。有了这两个类,我们就可以轻而易举的实现我们的功能。最后我们用一个button调用我么CD to wma的功能。在调用之前一定要现调用 hr = CoInitialize( NULL )用于初始化。下面把CCAudioInput和CWmvWriter类的主要部分贴出。

CCAudioInput.h:

#pragma once
#include <ntddcdrm.h>    // NT4DDK库
#include <winioctl.h>
#include <Mmreg.h>

// CCDAudioInput command target

#define  NSECTORS  13
#define  UNDERSAMPLING 1
#define  CB_CDDASECTOR 2368
#define  CB_QSUBCHANNEL 16
#define   CB_CDROMSECTOR 2048
#define  CB_AUDIO  (CB_CDDASECTOR-CB_QSUBCHANNEL)

class CCDAudioInput
{
public:
 CStringArray m_Tracks;   // the array of audio track
 CStringArray m_TrackTitles;  // the array of track title
 CString m_sArtist;    // the cd's artist
 CString m_sDrive;    // the CD-ROM drive name  
 HANDLE m_hDevice;    // the Device Handle of CD-ROM
 CDROM_TOC CdromTOC;
public:
 CCDAudioInput(CString &Drive);
 CCDAudioInput(const CCDAudioInput &cdInfo);
 CCDAudioInput();
 virtual ~CCDAudioInput();
 // Decide the CDROM if is ready
 BOOL IsReady(void);
 // Get the end of sector
 DWORD GetEndSector(int nTrack);
 // Get the start sector
 DWORD GetStartSector(int nTrack);
 // Read sector data to Buffer from CD-ROM
 BOOL ReadSector(int Sector, BYTE Buffer[], int NumSectors);
 CCDAudioInput& operator=(const CCDAudioInput &m_cdInfo);
};

CCAudioInput.cpp:

#include "stdafx.h"
#include "CDAudioInput.h"
#include "./cdaudioinput.h"

// CCDAudioInput
// CCDAudioInput member functions
CCDAudioInput::CCDAudioInput()
{
 m_sArtist = "";
 m_hDevice = INVALID_HANDLE_VALUE;
 m_Tracks.RemoveAll();
}
CCDAudioInput::CCDAudioInput(CString &Drive)
{
 m_sDrive = Drive;
 m_hDevice = CreateFile(".//"+m_sDrive, GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
      OPEN_EXISTING, 0, NULL);
}

CCDAudioInput::CCDAudioInput(const CCDAudioInput &cdInfo)
{
 m_sDrive = cdInfo.m_sDrive;
 m_hDevice = cdInfo.m_hDevice;
 m_sArtist = cdInfo.m_sArtist;
 m_Tracks.Copy(cdInfo.m_Tracks); 
}
CCDAudioInput::~CCDAudioInput()
{
}

CCDAudioInput& CCDAudioInput::operator=(const CCDAudioInput &m_cdInfo)
{
 if(this != &m_cdInfo)
 {
  m_sDrive = m_cdInfo.m_sDrive;
  m_hDevice = m_cdInfo.m_hDevice;
  m_sArtist = m_cdInfo.m_sArtist;
  m_Tracks.Copy(m_cdInfo.m_Tracks); 
 }
 return *this;
}

// Decide the CDROM if is ready
BOOL CCDAudioInput::IsReady(void)
{
 DWORD dwOutBytes;
 return (DeviceIoControl(m_hDevice,IOCTL_STORAGE_CHECK_VERIFY, NULL, 0,NULL, 0, &dwOutBytes, (LPOVERLAPPED)NULL));
}

//  Get the end of sector
DWORD CCDAudioInput::GetEndSector(int nTrack)
{
 return (CdromTOC.TrackData[nTrack].Address[1]*60*75 + CdromTOC.TrackData[nTrack].Address[2]*75 +
   CdromTOC.TrackData[nTrack].Address[3])-151;
}

//  Get the start sector
DWORD CCDAudioInput::GetStartSector(int nTrack)
{
 return (CdromTOC.TrackData[nTrack-1].Address[1]*60*75 + CdromTOC.TrackData[nTrack-1].Address[2]*75 +
  CdromTOC.TrackData[nTrack-1].Address[3])-150;
}

BOOL CCDAudioInput::ReadSector(int Sector, BYTE Buffer[], int NumSectors)
{
 DWORD dwOutBytes;
 RAW_READ_INFO rri;
 rri.TrackMode =(TRACK_MODE_TYPE)2;
 rri.SectorCount = (DWORD)NumSectors;
 rri.DiskOffset.QuadPart = (DWORD64)(Sector*CB_CDROMSECTOR);
 if (DeviceIoControl(m_hDevice,IOCTL_CDROM_RAW_READ,&rri, sizeof(rri), Buffer, (DWORD)NumSectors*CB_AUDIO,&dwOutBytes,(LPOVERLAPPED)NULL))   
   return TRUE;  
 return FALSE;
}

CWmvWriter.h:

#pragma once
// CWmvWriter command target
#include "wmsdk.h"         // windows media SDK header file
#include "wmsdkidl.h"      // windows media SDK header file
#include <Mmreg.h>
#include "wmsysprf.h"    // windows media SDK header file

#ifndef SAFE_RELEASE
    #define SAFE_RELEASE( x )           /
        if ( NULL != x )                /
        {                               /
            x->Release( );              /
            x = NULL;                   /
        }
#endif // SAFE_RELEASE

#ifndef SAFE_ARRAYDELETE
    #define SAFE_ARRAYDELETE( x )       /
       if( x )                          /
       {                                /
           delete [] x;                 /
           x = NULL;                    /
       }
#endif //SAFE_ARRAYDELETE

const LPWSTR wszDefaultConnectionName = L"CDTOWMA";

typedef struct MediaTypeTAG{
 WAVEFORMATEX m_pWFX;
 GUID   m_Type;
}MEDIATYPE, *PMEDIATYPE;

class CWmvWriter : public CObject
{
public:
 CWmvWriter();
 virtual ~CWmvWriter();
 HRESULT Initial(TCHAR* ptszInFile, TCHAR* ptszOutFile, IWMProfile* pProfile);
 HRESULT AddAudioStream(IWMProfile * pIWMProfile, DWORD dwSampleRate, DWORD dwChannels, WORD wBitsPerSample, WORD* pwStreamNum, WCHAR ** pwszConnectionName);
 HRESULT UpdateProfile(IWMProfile * pProfile);
public:
 IWMWriter  *m_pWMWriter;
 WM_MEDIA_TYPE mt;
// WAVEFORMATEX *m_pWFX;
 MEDIATYPE m_MediaType;
 HRESULT SetStreamBasics(IWMStreamConfig * pIWMStreamConfig, IWMProfile * pIWMProfile, LPWSTR pwszStreamName, LPWSTR pwszConnectionName, DWORD dwBitrate, WM_MEDIA_TYPE * pmt);
 HRESULT CreateEmptyProfile(IWMProfile ** ppIWMProfile);
 HRESULT WriteSample(BYTE* pBuffer, DWORD Length);
 DWORD m_AudioInput;
 DWORD m_MsAudioTime;
};

CWmvWriter.cpp:

// WmvWriter.cpp : implementation file

#include "stdafx.h"
#include "WmvWriter.h"
#include "./wmvwriter.h"

// CWmvWriter

CWmvWriter::CWmvWriter()
: m_AudioInput(0)
, m_MsAudioTime(0)
{
 m_pWMWriter = NULL;
 ZeroMemory(&m_MediaType, sizeof(MEDIATYPE));
}

CWmvWriter::~CWmvWriter()
{
}

HRESULT ConvertTCharToWChar( TCHAR * ptszInput, WCHAR ** pwszOutput )
{
    int cchOutput = 0;
   
    if( NULL == ptszInput || NULL == pwszOutput )
    {
        return( E_INVALIDARG );
    }

//
    // Get output buffer size
    //
#ifdef UNICODE
    cchOutput = wcslen( ptszInput ) + 1;
#else //UNICODE
    cchOutput = MultiByteToWideChar( CP_ACP, 0, ptszInput, -1, NULL, 0 );
    if( 0 == cchOutput )
    {
        return( HRESULT_FROM_WIN32( GetLastError() ) );
    }
#endif // UNICODE

*pwszOutput = new WCHAR[ cchOutput ];
    if( NULL == *pwszOutput)
    {
        return( E_OUTOFMEMORY );
    }

#ifdef UNICODE
    wcsncpy( *pwszOutput, ptszInput, cchOutput );
#else //UNICODE
    if( 0 == MultiByteToWideChar( CP_ACP, 0, ptszInput, -1, *pwszOutput, cchOutput ) )
    {
        SAFE_ARRAYDELETE( *pwszOutput );
        return( HRESULT_FROM_WIN32( GetLastError() ) );
    }       
#endif // UNICODE

return( S_OK );
}

// CWmvWriter member functions

HRESULT CWmvWriter::Initial(TCHAR* ptszInFile, TCHAR* ptszOutFile, IWMProfile* pProfile)
{
 HRESULT hr = S_OK;
 if((ptszOutFile == NULL) || (pProfile == NULL))
  return E_INVALIDARG;
 hr = WMCreateWriter(NULL, &m_pWMWriter);
 if(FAILED(hr))
 {
  AfxMessageBox("Failed to Create WMWriter.");
  return (hr);
 }
 hr = UpdateProfile(pProfile);
 if(FAILED(hr))
 {
  AfxMessageBox("Failed to Call UpdateProfile.");
  return (hr);
 }
 hr = m_pWMWriter->SetProfile(pProfile);
 if(FAILED(hr))
 {
  AfxMessageBox("Failed to Call SetProfile.");
  return hr;
 }
    if( NULL != ptszOutFile )
    {
        WCHAR * pwszOutFile = NULL;
  hr = ConvertTCharToWChar( ptszOutFile, &pwszOutFile );
  hr = m_pWMWriter->SetOutputFilename( pwszOutFile );
  SAFE_ARRAYDELETE( pwszOutFile );
  if(FAILED(hr))
  {
   AfxMessageBox("Failed to Call SetOutputFilename.");
   return (hr);
  }
 }
 return hr;
}

HRESULT CWmvWriter::UpdateProfile(IWMProfile * pProfile)
{
 HRESULT hr = S_OK;
 if(pProfile == NULL)
  return E_INVALIDARG;

m_MediaType.m_Type = WMMEDIATYPE_Audio;
 m_MediaType.m_pWFX.wFormatTag=WAVE_FORMAT_PCM ;
 m_MediaType.m_pWFX.nSamplesPerSec=48000;
 m_MediaType.m_pWFX.wBitsPerSample=16;
 m_MediaType.m_pWFX.nChannels=2;
 m_MediaType.m_pWFX.cbSize=0;
 m_MediaType.m_pWFX.nBlockAlign = m_MediaType.m_pWFX.nChannels*(m_MediaType.m_pWFX.wBitsPerSample/8);
 m_MediaType.m_pWFX.nAvgBytesPerSec = m_MediaType.m_pWFX.nSamplesPerSec*m_MediaType.m_pWFX.nBlockAlign;

WORD wStreamNum = 0;
 WCHAR *pwszConnectionName;
    hr = AddAudioStream( pProfile, m_MediaType.m_pWFX.nSamplesPerSec, m_MediaType.m_pWFX.nChannels
  , m_MediaType.m_pWFX.wBitsPerSample, &wStreamNum, &pwszConnectionName);
 if(FAILED(hr))
 {
  AfxMessageBox("Failed to Call AddAudioStream.");
  return hr;
 }
 return hr;
}

HRESULT CWmvWriter::AddAudioStream(IWMProfile * pIWMProfile, DWORD dwSampleRate, DWORD dwChannels,
           WORD wBitsPerSample, WORD* pwStreamNum, WCHAR ** pwszConnectionName)
{
 HRESULT hr = S_OK;
    IWMProfileManager   * pIWMProfileManager = NULL;
    IWMStreamConfig     * pIWMStreamConfig = NULL;
    IWMMediaProps       * pIMP  = NULL;
    IWMCodecInfo        * pIWMInfo = NULL;
    WAVEFORMATEX        * pWfx = NULL;
    WM_MEDIA_TYPE       * pType = NULL;
 if((NULL == pIWMProfile) || (NULL == pwStreamNum))
  return E_INVALIDARG;
 do{
  hr = WMCreateProfileManager(&pIWMProfileManager);
  if(FAILED(hr)) break;
  hr = pIWMProfileManager->QueryInterface(IID_IWMCodecInfo, (void**) &pIWMInfo);
  if(FAILED(hr)) break;
        DWORD i, j;
        DWORD cCodecs;
  hr = pIWMInfo->GetCodecInfoCount(WMMEDIATYPE_Audio, &cCodecs);
  if(FAILED(hr)) break;
  for(i=0; i<cCodecs; i++)
  {
            DWORD cFormats;
            hr = pIWMInfo->GetCodecFormatCount( WMMEDIATYPE_Audio, i, &cFormats );
   if( FAILED( hr ) ) break;
            // Find a proper format in this codec
   for(j=0; j<cFormats; j++)
   {
    if( NULL != pType )
     SAFE_ARRAYDELETE( pType );
    DWORD cbType = 0;
                hr = pIWMInfo->GetCodecFormat( WMMEDIATYPE_Audio, i, j, &pIWMStreamConfig );
    if(FAILED(hr)) break;
    SAFE_RELEASE( pIMP );
                hr = pIWMStreamConfig->QueryInterface( IID_IWMMediaProps, (void **)&pIMP );
    if(FAILED(hr)) break;
    hr = pIMP->GetMediaType( NULL, &cbType );
    if(FAILED(hr)) break;
    pType = (WM_MEDIA_TYPE *) new BYTE[ cbType ];
                if( NULL == pType )
                {
                    hr = E_OUTOFMEMORY;
                    break;
                }
    hr = pIMP->GetMediaType( pType, &cbType );
    if(FAILED(hr)) break;
                if( pType->formattype != WMFORMAT_WaveFormatEx )
                {
                    hr = E_FAIL;
                    break;
                }
     pWfx = (WAVEFORMATEX *) pType->pbFormat;
                if( pWfx->nSamplesPerSec == dwSampleRate && pWfx->nChannels == dwChannels &&
                    pWfx->wBitsPerSample >= wBitsPerSample )
                {
                    break;
                }
    SAFE_RELEASE( pIWMStreamConfig );
   }
            if( FAILED( hr ) || NULL != pIWMStreamConfig )
    break;
  }
  if(FAILED(hr)) break;
        if( NULL == pIWMStreamConfig )
        {
            hr = NS_E_AUDIO_CODEC_NOT_INSTALLED;
            break;
        }
        hr = SetStreamBasics( pIWMStreamConfig,
                              pIWMProfile,
                              L"Audio Stream",
                              L"Audio",
                              pWfx->nAvgBytesPerSec * 8,
                              pType );
        if( FAILED( hr ) )
        {
            break;
        }

*pwszConnectionName = new WCHAR[ wcslen( wszDefaultConnectionName ) + 4 ];
        if( NULL == *pwszConnectionName )
        {
            hr = E_OUTOFMEMORY;
            break;
        }

hr = pIWMProfile->AddStream( pIWMStreamConfig );
        if( FAILED( hr ) )
        {
            SAFE_ARRAYDELETE( *pwszConnectionName );
            break;
        }

hr = pIWMStreamConfig->GetStreamNumber( pwStreamNum );
        if( FAILED( hr ) )
        {
            SAFE_ARRAYDELETE( *pwszConnectionName );
            break;
        }

//
        // each stream in the profile has to have unique connection name
        // let's use stream number to create it
        //

if( *pwStreamNum > 127 )
        {
            hr = E_FAIL;
            break;
        }

swprintf( *pwszConnectionName, L"%s%d", wszDefaultConnectionName, (DWORD)*pwStreamNum );

hr = pIWMStreamConfig->SetConnectionName( *pwszConnectionName );
        if( FAILED( hr ) )
        {
            SAFE_ARRAYDELETE( *pwszConnectionName );
            break;
        }

hr = pIWMProfile->ReconfigStream( pIWMStreamConfig );
        if( FAILED( hr ) )
        {
            SAFE_ARRAYDELETE( *pwszConnectionName );
            break;
        }
    }
    while( FALSE );

SAFE_ARRAYDELETE( pType );
    SAFE_RELEASE( pIWMInfo );
    SAFE_RELEASE( pIWMStreamConfig );
    SAFE_RELEASE( pIMP );
    SAFE_RELEASE( pIWMProfileManager );

return( hr );
}

HRESULT CWmvWriter::SetStreamBasics(IWMStreamConfig *pIWMStreamConfig, IWMProfile *pIWMProfile, LPWSTR pwszStreamName,
         LPWSTR pwszConnectionName, DWORD dwBitrate, WM_MEDIA_TYPE * pmt)
{
    HRESULT hr = S_OK;
    IWMMediaProps * pIWMMediaProps = NULL;
    IWMStreamConfig * pIWMStreamConfig2 = NULL;
    WORD wStreamNum = 0;

if( NULL == pIWMStreamConfig || NULL == pIWMProfile || NULL == pmt )
    {
        return( E_INVALIDARG );
    }

do
    {
        hr = pIWMProfile->CreateNewStream( pmt->majortype, &pIWMStreamConfig2 );
        if( FAILED( hr ) )
        {
            break;
        }

hr = pIWMStreamConfig2->GetStreamNumber( &wStreamNum );
        SAFE_RELEASE( pIWMStreamConfig2 );
        if( FAILED( hr ) )
        {
            break;
        }

hr = pIWMStreamConfig->SetStreamNumber( wStreamNum );
        if( FAILED( hr ) )
        {
            break;
        }

hr = pIWMStreamConfig->SetStreamName( pwszStreamName );
        if( FAILED( hr ) )
        {
            break;
        }

hr = pIWMStreamConfig->SetConnectionName( pwszConnectionName );
        if( FAILED( hr ) )
        {
            break;
        }

hr = pIWMStreamConfig->SetBitrate( dwBitrate );
        if( FAILED( hr ) )
        {
            break;
        }

hr = pIWMStreamConfig->QueryInterface( IID_IWMMediaProps,
                                               (void **) &pIWMMediaProps );
        if( FAILED( hr ) )
        {
            break;
        }

hr = pIWMMediaProps->SetMediaType( pmt );
        if( FAILED( hr ) )
        {
            break;
        }
    }
    while( FALSE );

SAFE_RELEASE( pIWMMediaProps );

return( hr );
}

HRESULT CWmvWriter::CreateEmptyProfile(IWMProfile ** ppIWMProfile)
{
    HRESULT             hr = S_OK;
    IWMProfileManager*  pIWMProfileManager = NULL;
    if( NULL == ppIWMProfile )
    {
        return( E_POINTER );
    }
    do
    {
        //
        // Create profile manager
        //
        hr = WMCreateProfileManager( &pIWMProfileManager );
        if( FAILED( hr ) )
        {
            break;
        }
        hr = pIWMProfileManager->CreateEmptyProfile( WMT_VER_8_0, ppIWMProfile );
        if( FAILED( hr ) )
        {
            break;
        }
    }
    while( FALSE );
    //
    // Release all resources
    //
    SAFE_RELEASE( pIWMProfileManager );
    return( hr );
}

HRESULT CWmvWriter::WriteSample(BYTE* pBuffer, DWORD Length)
{
 HRESULT hr = S_OK;
 if(m_pWMWriter != NULL)
 {
  INSSBuffer *pSample;
  BYTE *pSampleBuff;
  HRESULT hr = m_pWMWriter->AllocateSample(Length, &pSample);
  if(FAILED(hr))
  {
   AfxMessageBox("Call AllocateSample Failure!");
   return hr;
  }
  pSample->GetBufferAndLength(&pSampleBuff, &Length);
  memcpy(pSampleBuff, pBuffer, Length);
  pSample->SetLength(Length);
//  Write(pSample);
  hr = m_pWMWriter->WriteSample(m_AudioInput, m_MsAudioTime * 10000, 0, pSample);
  if(FAILED(hr))
  {
   AfxMessageBox("Call WriteSample Failure!");
   return hr;
  }
  m_MsAudioTime += MulDiv(Length, 1000, m_MediaType.m_pWFX.nAvgBytesPerSec);
 }else AfxMessageBox("Write Sample Fail!"); 
 return hr;
}

类的实现有了,那现在实现button的功能吧,为了方便描述,我这里只是把CD的Track1转为wma。

BYTE Data[CB_AUDIO*NSECTORS];
 int StartSector, EndSector, Sectors2Read;
 StartSector = cdInfo->GetStartSector(1);       // cdInfo是一个CCDAudioInput类指针
 EndSector = cdInfo->GetEndSector(1);
 m_Progress.SetRange(0, EndSector - StartSector);   // m_Progress是进度条
 strcat(MusicDir, "Track1.wma");    // MusicDir是输出文件
 HRESULT hr = S_OK;
 hr = CoInitialize( NULL );      // 记得调用初始化
 CWmvWriter m_Writer;
 IWMProfile *pProfile;
 m_Writer.CreateEmptyProfile(&pProfile);
 m_Writer.Initial("", MusicDir, pProfile);
 m_Writer.m_pWMWriter->BeginWriting();
 for(int sector=StartSector; sector<EndSector; sector+=NSECTORS)
 {
  Sectors2Read = ( (sector + NSECTORS) < EndSector )?NSECTORS:(EndSector-sector);
  if (cdInfo->ReadSector(sector, Data, Sectors2Read))
  {    
   hr = m_Writer.WriteSample(Data, sizeof(Data));
   if(FAILED(hr))
   {
    AfxMessageBox("Failed to WriteSample.");
    break;
   }
   m_Progress.SetPos(m_Progress.GetPos() + Sectors2Read);
  }
 }
 m_Writer.m_pWMWriter->Flush();
 m_Writer.m_pWMWriter->EndWriting();
}

结尾:

为了能编译这个程序,你要安装NT4DDK开发包并包含里面的头文件,主要用于对CD音轨的操作,然后还要加入windows media SDK的头文件以及kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib msvcrtd.lib wmvcore.lib winmm.lib odbc32.lib odbccp32.lib 库文件。

好了,今天就到此为止,有什么question,please mailto: ss_liao@163.com, MSN: ss_liao@163.com。大家一起study。Thanks!!!

怎样抓CD音轨存为WMA文件相关推荐

  1. 用什么软件抓cd音轨音质最好_什么APP听音乐好?

    年纪大了,果然和世界的接轨慢八拍,我居然刚刚得知诸如QQ音乐等各大APP,有些著名歌手连听歌都开始收费了. 这当然是好事情. 多年一路过来,也捣腾了很多听音乐的APP,下边把自己的一些见解和经验分享一 ...

  2. 用什么软件抓cd音轨音质最好_开车不嗨皮,那跟咸鱼有什么区别

    文 | 大青枣 图 | 潘隐 跑长途是件很无聊的事情,看着车窗外的车水马龙,想到接下来的漫漫长路,立马就想打盹. 但正所谓行车不规范,亲人两行泪.所以为了让能够安全并快乐的从A点到B点.司机和主机厂都 ...

  3. 用什么软件抓cd音轨音质最好_什么是音乐制作以及工作流程?

    什么是音乐制作? 音乐制作人是二十世纪九十年代出现的一个新兴的职业. 音乐制作指的是制作一首音乐作品的工作统称,包括写歌词.作曲.编曲.录音.混音.母带处理等工作也是音乐制作中的工作流程. 通常是团队 ...

  4. Python爬取的数据存为json文件,并读取

    Python爬取的数据存为json文件,并读取 import requests import time from lxml import etree import jsondef json_data_ ...

  5. ffmpeg解码视频存为BMP文件

    ffmpeg解码视频存为BMP文件 分类: ffmpeg2011-07-28 12:13 8人阅读 评论(0) 收藏 举报 view plain #include <windows.h> ...

  6. 成功解决使用jupyter notebook命令打开原先存的.ipynb文件突然消失的问题

    成功解决使用jupyter notebook命令打开原先存的.ipynb文件突然消失的问题 目录 解决问题 解决思路 解决方法 T1.修改默认配置

  7. Python将list存为csv文件

    #!/usr/bin/env python # -*- encoding: utf-8 -*-import sys import json import os import pandas as pd& ...

  8. HTML 表单 存为EXCEL文件时 中文显示乱码

    在做宣传品发放系统时,需求要把数据库查询的记录生成表单并转存excel文件. 在转存的EXCEL文件中文显示乱码,表格和其他字符正常,检查后发现是创建EXCEL文件打开模式不对 之前: myfile ...

  9. 模拟运行php,window_PHP+Javascript模拟Matrix画面, 直接存为*.php文件运行即 - phpStudy...

    PHP+Javascript模拟Matrix画面 直接存为*.php文件运行即可. $color_back="#000000"; $number_w=8; $number_h=6; ...

最新文章

  1. 机器人学习--ROS/AMCL实现初始化粒子撒满整张地图和分步收敛
  2. html设置文字超过字数_css限制文字显示字数长度,超出部分自动用省略号显示,防止溢出到第二行...
  3. poj3069 Saruman's Army(贪心)
  4. epoll socket 服务端中read和write的返回值讨论
  5. tableau可视化_如何在Tableau中构建自定义地图可视化
  6. html th表格居中,HTML----之表格
  7. 时间太少,如何阅读?
  8. python 今日头条 控制手机_你知道Python脚本控制安卓手机可以用来做什么吗?
  9. php 实现贪心算法,python贪心算法如何实现 python贪心算法实现代码示例
  10. k8s pod部署到不同node_应用部署演进(二)
  11. 图学习(二)K-armed Bandit based Multi-modal Network Architecture Search for Visual Question Answering
  12. 网络安全之路:我的系统性渗透测试学习框架
  13. fb静态区域_FC 与 FB 与 OB 的区别,时间标记冲突与一致性检查 有详细的步骤...
  14. 微信小程序 -- 原生JS集成腾讯IM实时聊天/实时音视频(踩坑及心得)
  15. 【控制】鲁棒性 H2 H无穷
  16. 在Ubuntu 上安装和配置Snort 3 NIDS
  17. 联手友盟+打造数据融合“样板间”, 好兔视频成功逆势突围
  18. ADB 操作命令及用法
  19. mac Anaconda matplotlib 中文乱码问题
  20. 平狄克《微观经济学》第八版笔记和课后答案

热门文章

  1. “非图灵完备”到底意味着什么
  2. FL Studio电音编曲软件V21中文完整版 安装下载教程
  3. 问题:TypeError: Descriptors cannot not be created directly.解决方法
  4. vue 敏感词过滤 前端
  5. 微信公众号JS-SDK多图上传爬坑指南
  6. EVM源码解读(1):amplify_spatial_lpyr_temporal_iir函数
  7. APP启动方式分析——冷启动、热启动、温启动
  8. 一些常用的数学在线计算器
  9. 在纽约寻找童真——新泽西州乐高乐园探索中心的美好一天
  10. 鼠标变成方块而不是竖线