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

📄 ff_wmv9.cpp

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "stdafx.h"
#include "ff_wmv9.h"
#include "GenProfile_lib.h"
#include "writerSink.h"
#include "Twmv9dll.h"

#include <strmif.h>
#include <mediaobj.h>
#include "encode.h"
#include "encappErr.h"
#include "videoenc.h"
#include <uuids.h>
#include "baseclasses/amvideo.h"

#include "imgFilters/ffImgfmt.h"
#include <initguid.h>
#include "ffdshow_mediaguids.h"
#include "../../compiler.h"
#ifdef __GNUC__
 #include "strmiids.cpp"
#else
 DEFINE_GUID(IID_IMediaObject,0xd8ad0f58,0x5494,0x4102,0x97,0xc5,0xec,0x79,0x8e,0x59,0xbc,0xf4);
 DEFINE_GUID(MEDIASUBTYPE_IYUV,0x56555949,0x0,0x10,0x80,0x0,0x0,0xAA,0x0,0x38,0x9B,0x71);
#endif

#if DEBUG
#define DEBUGS(s) OutputDebugString(s)
#else
#define DEBUGS(s)
#endif

using namespace std;

bool operator <(const Tff_wmv9codecInfo &c1,const Tff_wmv9codecInfo &c2)
{
 return stricmp(c1.name,c2.name)<0;
}

struct Tff_wmv9 :public Iff_wmv9
{
private:
 Tff_wmv9cfg cfg;
 IWMProfile *pProfile;
 IWMCodecInfo3 *m_pCodecInfo;
 IWMWriter *pWMWriter;
 IWMWriterAdvanced *pWMWriterA;
 IWMWriterFileSink *filesink;
 TmyWriterSink *mysink;
 int wrinputnum;
 bool ok,writing;
 std::vector<Tff_wmv9codecInfo> codecs;
 Twmv9dll *wmv9dll;
public:
 Tff_wmv9(void)
  {
   ok=false;
   pProfile=NULL;m_pCodecInfo=NULL;
   pWMWriter=NULL;pWMWriterA=NULL;
   mysink=NULL;filesink=NULL;
   memset(&cfg,0,sizeof(cfg));

   wmv9dll=new Twmv9dll;
   if (!wmv9dll->ok) return;

   #define JIF(x) if (FAILED(hr=(x))) {DEBUGS(_l("FAILED in ")_l(#x)_l("\n"));return;}
   HRESULT hr;
   JIF(EnsureIWMCodecInfo3(wmv9dll,&m_pCodecInfo));
   DWORD codecCount;
   m_pCodecInfo->GetCodecInfoCount(WMMEDIATYPE_Video,&codecCount);
   for (DWORD i=0;i<codecCount;i++)
    {
     WCHAR codecName[1024];
     DWORD codecNameLength=1024;
     if (SUCCEEDED(m_pCodecInfo->GetCodecName(WMMEDIATYPE_Video,i,codecName,&codecNameLength)))
      {
       codecName[codecNameLength]=L'\0'; // terminate the codec name, just in case
       Tff_wmv9codecInfo info;memset(&info,0,sizeof(info));
       info.index=i;
       //WideCharToMultiByte(CP_ACP,0,codecName,-1,info.name,256,NULL,NULL);
       strcpy(info.name,text<char_t>(codecName));
       WMT_ATTR_DATATYPE type;
       BOOL isVBR;DWORD isVBRsize=sizeof(isVBR);
       if (SUCCEEDED(m_pCodecInfo->GetCodecProp(WMMEDIATYPE_Video,i,g_wszIsVBRSupported,&type,(BYTE*)&isVBR,&isVBRsize)))
        info.vbr=isVBR;
       DWORD cmplxMax,cmplxMaxSize=sizeof(cmplxMax);
       if (SUCCEEDED(m_pCodecInfo->GetCodecProp(WMMEDIATYPE_Video,i,g_wszComplexityMax,&type,(BYTE*)&cmplxMax,&cmplxMaxSize)))
        info.cmplxMax=cmplxMax;
       DWORD codecformatcount=0;
       m_pCodecInfo->GetCodecFormatCount(WMMEDIATYPE_Video,i,&codecformatcount);
       for (unsigned int j=0;j<min(DWORD(1),codecformatcount);j++)
        {
         IWMStreamConfig *wsc=NULL;
         WCHAR desc[256];DWORD desclen=256;
         if (SUCCEEDED(m_pCodecInfo->GetCodecFormatDesc(WMMEDIATYPE_Video,i,j,&wsc,desc,&desclen)))
          {
           IWMMediaProps *mp=NULL;
           if (SUCCEEDED(wsc->QueryInterface(IID_IWMMediaProps,(void**)&mp)))
            {
             DWORD typelen=0;
             if (SUCCEEDED(mp->GetMediaType(NULL,&typelen)) && typelen!=0)
              {
               WM_MEDIA_TYPE *type=(WM_MEDIA_TYPE*)malloc(typelen);
               mp->GetMediaType(type,&typelen);
               info.mediatype=type->subtype;
               info.fcc=type->subtype.Data1;
               codecs.push_back(info);
               free(type);
              }
             mp->Release();
            }
           wsc->Release();
          }
        }
      }
    }
   sort(codecs.begin(),codecs.end());
   ok=true;
  }
 virtual ~Tff_wmv9()
  {
   end();
   delete wmv9dll;
  }
 virtual bool __stdcall getOk(void) {return ok;}
 virtual size_t  __stdcall getCodecCount(void) {return codecs.size();}
 virtual bool __stdcall getCodecInfo(size_t i,const Tff_wmv9codecInfo* *info)
  {
   if (i>=codecs.size() || !info) return false;
   *info=&codecs[i];
   return true;
  }
 virtual bool __stdcall start(const Tff_wmv9cfg &Icfg)
  {
   cfg=Icfg;
   if (cfg.avioutput) return startAVI();
   writing=false;
   #undef JIF
   #define JIF(x) if (FAILED(hr=(x))) {DEBUGS(_l("FAILED in ")_l(#x)_l("\n"));return false;}
   HRESULT hr;
   IWMProfileManager *pProfileManager=NULL;
   JIF(wmv9dll->WMCreateProfileManager(&pProfileManager));
   JIF(pProfileManager->CreateEmptyProfile(WMT_VER_9_0,&pProfile));
   IWMProfile3 *pProfile3=NULL;
   JIF(pProfile->QueryInterface(IID_IWMProfile3,(void**)&pProfile3));

   JIF(pProfile->SetName(L"ff_wmv9 profile"));
   JIF(pProfile->SetDescription(L"ff_wmv9 description"));

   IWMStreamConfig *pNewStreamConfig=NULL;
   JIF(CreateVideoStream(wmv9dll,
                         &pNewStreamConfig,
                         m_pCodecInfo,
                         pProfile,
                         cfg.codecIndex,  // codec index
                         cfg.bitrate,       // bitrate
                         3000, // buffer window
                         cfg.width, // width
                         cfg.height, // height
                         cfg.fps,  // fps
                         cfg.quality, // video quality
                         cfg.seckf,  // seconds per keyframes
                         cfg.bUseVBR, // video is VBR
                         cfg.vbr_mode, // VBR mode ( VIDEO_VBR_MODE )
                         cfg.vbrquality, // VBR Quality
                         cfg.maxbitrate, // Max Bitrate (VBR)
                         10000,      // Max VBR Video Buffer
                         GetSystemDefaultLCID()));

   JIF(pNewStreamConfig->SetStreamNumber(1));
   JIF(pNewStreamConfig->SetStreamName(L"Video"));
   #define CONN_NAME L"VideoConnect"
   JIF(pNewStreamConfig->SetConnectionName(CONN_NAME));
   JIF(pNewStreamConfig->SetBufferWindow(3000));

   IWMPropertyVault *strprops=NULL;
   if (SUCCEEDED(pNewStreamConfig->QueryInterface(IID_IWMPropertyVault,(void**)&strprops)))
    {
     WORD cplx=(WORD)cfg.cplx;if (cplx>codecs[cfg.codecIndex].cmplxMax) cplx=WORD(codecs[cfg.codecIndex].cmplxMax);
     strprops->SetProperty(g_wszComplexity,WMT_TYPE_WORD,(BYTE*)&cplx,sizeof(cplx));
     strprops->Release();
    }

   JIF(pProfile->AddStream(pNewStreamConfig));
   pNewStreamConfig->Release();pNewStreamConfig=NULL;
   pProfile3->Release();pProfile3=NULL;
   pProfileManager->Release();pProfileManager=NULL;

   JIF(wmv9dll->WMCreateWriter(NULL,&pWMWriter));
   JIF(pWMWriter->QueryInterface(IID_IWMWriterAdvanced,(void**)&pWMWriterA));
   JIF(pWMWriter->SetProfile(pProfile));
   DWORD inpcnt=0;
   pWMWriter->GetInputCount(&inpcnt);
   wrinputnum=-1;
   for (DWORD i=0;i<inpcnt && wrinputnum==-1;i++)
    {
     IWMInputMediaProps *props=NULL;
     JIF(pWMWriter->GetInputProps(i,&props));
     WCHAR connNameW[256];WORD connNameLen=256;
     props->GetConnectionName(connNameW,&connNameLen);
     if (wcscmp(connNameW,CONN_NAME)==0)
      wrinputnum=i;
     props->Release();
    }
   if (wrinputnum==-1) return false;
   DWORD fmtcnt=0;
   pWMWriter->GetInputFormatCount(wrinputnum,&fmtcnt);
   WM_MEDIA_TYPE *mediatype=NULL;
   IWMInputMediaProps *props=NULL;
   for (DWORD fmti=0;fmti<fmtcnt && !mediatype;fmti++)
    {
     JIF(pWMWriter->GetInputFormat(wrinputnum,fmti,&props));
     DWORD mtsize;
     JIF(props->GetMediaType(NULL,&mtsize));
     mediatype=(WM_MEDIA_TYPE*)malloc(mtsize);
     JIF(props->GetMediaType(mediatype,&mtsize));
     if (mediatype->subtype==WMMEDIASUBTYPE_YV12) break;
     free(mediatype);mediatype=NULL;
     props->Release();props=NULL;
    }
   if (!mediatype) return false;
   //here we could modify input type settings, but they seem to be OK already
   //WMVIDEOINFOHEADER *wvih=(WMVIDEOINFOHEADER*)mediatype->pbFormat;
   // BITMAPINFOHEADER &bih=wvih->bmiHeader;
   pWMWriter->SetInputProps(wrinputnum,props);
   free(mediatype);
   props->Release();
   IWMWriterAdvanced2 *writerA2=NULL;
   if (SUCCEEDED(pWMWriter->QueryInterface(IID_IWMWriterAdvanced2,(void**)&writerA2)))
    {
     if (cfg.ivtc)
      {
       DWORD a=WM_DM_DEINTERLACE_INVERSETELECINE;
       hr=writerA2->SetInputSetting(wrinputnum,g_wszDeinterlaceMode,WMT_TYPE_DWORD,(const unsigned char *)&a,sizeof(DWORD));
      }
     if (cfg.deint)
      {
       DWORD a=WM_DM_DEINTERLACE_NORMAL;
       hr=writerA2->SetInputSetting(wrinputnum,g_wszDeinterlaceMode,WMT_TYPE_DWORD,(const unsigned char *)&a,sizeof(DWORD));
      }
     writerA2->Release();
    }

   if (0)
    {
     mysink=new TmyWriterSink(NULL,&hr);
     pWMWriterA->AddSink((IWMWriterSink*)mysink);
    }
   if (cfg.flnm)
    {
     wmv9dll->WMCreateWriterFileSink(&filesink);
     //WCHAR flnmW[MAX_PATH];
     //MultiByteToWideChar(CP_ACP,0,cfg.flnm,(int)strlen(cfg.flnm)+1,flnmW,MAX_PATH);
     filesink->Open(text<wchar_t>(cfg.flnm));
     pWMWriterA->AddSink(filesink);
    }
   JIF(pWMWriter->BeginWriting());
   writing=true;
   return true;
  }
 virtual int __stdcall write(unsigned int framenum,int csp,const unsigned char * const src[4],const stride_t srcStride[4],void *dst)
  {
   if (!writing) return 0;
   if (cfg.avioutput) return writeAVI(framenum,csp,src,srcStride,dst);
   INSSBuffer *buf=NULL;
   if (SUCCEEDED(pWMWriter->AllocateSample(3*cfg.width*cfg.height/2,&buf)))
    {
     BYTE *bufptr=NULL;
     buf->GetBuffer(&bufptr);
     DWORD buflen=3*cfg.width*cfg.height/2;
     memcpy(bufptr,src[0],buflen); //always XVID_CSP_YV12
     buf->SetLength(buflen);
     HRESULT res=pWMWriter->WriteSample(wrinputnum,QWORD(framenum*int64_t(10000000)/cfg.fps),0,buf);
     buf->Release();
     return 1;
    }
   else
    return 0;
  }
 virtual void __stdcall end(void)
  {
   if (cfg.avioutput)
    {
     endAVI();
     return;
    }
   if (pWMWriter)
    {
     if (writing) pWMWriter->EndWriting();writing=false;
     if (filesink) filesink->Release();filesink=NULL;
     if (mysink) mysink->Release();mysink=NULL;
     if (pWMWriterA) pWMWriterA->Release();pWMWriterA=NULL;
     if (pWMWriter) pWMWriter->Release();pWMWriter=NULL;
    }
   if (pProfile) pProfile->Release();pProfile=NULL;
   if (m_pCodecInfo) m_pCodecInfo->Release();m_pCodecInfo=NULL;
  }
private:
 struct Tcontext
  {
   Tcontext(void)
    {
     memset(this,0,sizeof(*this));
    }
   IMediaObject *pDMO;
   AM_MEDIA_TYPE mtIn;
   AM_MEDIA_TYPE mtOut;
   CHandlingMediaBuffer *pInputBuffer;
   CHandlingMediaBuffer *pOutputBuffer;
   REFERENCE_TIME       rtDecimatorTimeStamp;
   REFERENCE_TIME       rtDecimatorDuration;
   REFERENCE_TIME       rtMaxJitter;
   REFERENCE_TIME       rtFrameDuration;
   REFERENCE_TIME       rtTimeStamp;
   unsigned char *input;unsigned int inputSize;
   unsigned char *output;unsigned int outputSize;
  } pContext;
 VideoEncParams pParams;
 int nOutFrames;
 DWORD cbVideoOut;
 HRESULT InitializeEncoder(IMediaObject  **ppDMO,
                           AM_MEDIA_TYPE *pmtIn,
                           AM_MEDIA_TYPE *pmtOut,
                           CHandlingMediaBuffer *pMediaBuffer)
  {
   HRESULT hr=S_OK;
   if (!ppDMO ||!pmtIn || !pmtOut) return E_INVALIDARG;
   hr=InitializeVideoEncoder(pmtIn,
                             &pParams,
                             ppDMO,
                             pmtOut,
                             pMediaBuffer);
   return ( hr );
  }
 bool startAVI(void)
  {
   cbVideoOut = max(128 * 128 * 2,
                    (((cfg.width  + 15) & ~15) *
                     ((cfg.height + 15) & ~15) * 3));
   HRESULT  hr=S_OK;
   DWORD dwFlags;
   VIDEOINFOHEADER *vih=(VIDEOINFOHEADER*)CoTaskMemAlloc(sizeof(VIDEOINFOHEADER));
   vih->rcSource.left=0;vih->rcSource.top=0;vih->rcSource.right=cfg.width;vih->rcSource.bottom=cfg.height;
   vih->rcTarget=vih->rcSource;
   vih->dwBitRate=DWORD(3*cfg.fps*cfg.width*cfg.height/2);
   vih->dwBitErrorRate=0;
   vih->AvgTimePerFrame=REFERENCE_TIME(10000000.0/cfg.fps);
   vih->bmiHeader.biSize=sizeof(vih->bmiHeader);
   vih->bmiHeader.biWidth=cfg.width;
   vih->bmiHeader.biHeight=cfg.height;
   vih->bmiHeader.biPlanes=1;
   const TcspInfo *cspInfo=csp_getInfo(cfg.csp);
   vih->bmiHeader.biBitCount=WORD(cspInfo->bpp);
   vih->bmiHeader.biCompression=cspInfo->fcc;
   vih->bmiHeader.biSizeImage=cspInfo->bpp*cfg.width*cfg.height/8;
   pContext.mtIn.subtype=*cspInfo->subtype;
   vih->bmiHeader.biXPelsPerMeter=0;
   vih->bmiHeader.biYPelsPerMeter=0;
   vih->bmiHeader.biClrUsed=0;
   vih->bmiHeader.biClrImportant=0;
   pContext.pDMO=NULL;
   pContext.pInputBuffer=new CHandlingMediaBuffer;
   pContext.mtIn.majortype=MEDIATYPE_Video;
   pContext.mtIn.bFixedSizeSamples=TRUE;
   pContext.mtIn.bTemporalCompression=FALSE;
   pContext.mtIn.formattype=FORMAT_VideoInfo;
   pContext.mtIn.lSampleSize=vih->bmiHeader.biSizeImage;
   pContext.mtIn.pUnk=NULL;
   pContext.mtIn.cbFormat=sizeof(VIDEOINFOHEADER);
   pContext.mtIn.pbFormat=(unsigned char*)vih;
   pContext.input=(unsigned char*)malloc(pContext.inputSize=pContext.mtIn.lSampleSize);

   pContext.pOutputBuffer=new CHandlingMediaBuffer;
   memset(&pContext.mtOut,0,sizeof(pContext.mtOut));

   pParams.nBitrate=cfg.bitrate;
   pParams.nWidth=cfg.width;
   pParams.nHeight=cfg.height;
   pParams.dFrameRate=cfg.fps;
   pParams.nKeyDist=cfg.seckf*1000;
   pParams.nBufferDelay=5000;
   pParams.nCrisp=cfg.crisp;
   pParams.nQuality=cfg.quality;
   pParams.nPeakBuffer=5000;
   pParams.nPeakBitrate=cfg.maxbitrate;
   pParams.nComplexity=cfg.cplx;
   pParams.nProfile=P_MAIN;
   pParams.fIsVBR=cfg.bUseVBR;
   pParams.fIsConstrained=FALSE;
   pParams.fIsInterlaced=cfg.deint;
   pParams.nPasses=1;
   for (vector<Tff_wmv9codecInfo>::const_iterator c=codecs.begin();c!=codecs.end();c++)
    if (c->index==cfg.codecIndex)
     {
      pParams.dwTag=c->fcc;
      break;
     }
   hr=InitializeEncoder(&pContext.pDMO,
                        &pContext.mtIn,
                        &pContext.mtOut,
                        pContext.pInputBuffer);
   if (FAILED(hr)) return false;

   //
   // The codecs used in this sample don't perform lookahead on the incoming data.
   // If this changes the scheme used here may not work.
   // FAIL is the encoder uses lookahead.
   //
   hr = pContext.pDMO->GetInputStreamInfo( 0, &dwFlags );

⌨️ 快捷键说明

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