00001 #include "StdAfx.h"
00002 #include "AviReportWnd.h"
00003
00004 #define IDC_DONOTSHOWAGAINCHECK 1000
00005 #define TITLE _T("AVI Chunk Viewer")
00006 #define GRAPHFOOTER 10
00007
00008 CAviReportWnd::CAviReportWnd()
00009 {
00010 m_font.CreateFont(12, 0, 0, 0, 400, 0, 0, 0, 1, 0, 0, 0, 0, _T("MS Shell Dlg"));
00011 }
00012
00013 bool CAviReportWnd::DoModal(CAviFile* pAF, bool fHideChecked, bool fShowWarningText)
00014 {
00015 m_nChunks = 0;
00016 m_rtDur = 0;
00017
00018 for(int i = 0; i < (int)pAF->m_avih.dwStreams; i++)
00019 {
00020 int cnt = pAF->m_strms[i]->cs2.GetCount();
00021 if(cnt <= 0) continue;
00022 CAviFile::strm_t::chunk2& c2 = pAF->m_strms[i]->cs2[cnt-1];
00023 m_nChunks = max(m_nChunks, c2.n);
00024 m_rtDur = max(m_rtDur, (REFERENCE_TIME)c2.t<<13);
00025 }
00026
00027 CRect r, r2;
00028 GetDesktopWindow()->GetWindowRect(r);
00029 r.DeflateRect(r.Width()/4, r.Height()/4);
00030
00031 LPCTSTR wndclass = AfxRegisterWndClass(
00032 CS_VREDRAW|CS_HREDRAW|CS_DBLCLKS,
00033 AfxGetApp()->LoadStandardCursor(IDC_ARROW),
00034 (HBRUSH)(COLOR_BTNFACE + 1), 0);
00035
00036 CreateEx(0, wndclass, TITLE, WS_POPUPWINDOW|WS_CAPTION|WS_CLIPCHILDREN, r, NULL, 0);
00037
00038 CRect cr;
00039 GetClientRect(cr);
00040 cr.DeflateRect(10, 10);
00041
00042 SetFont(&m_font, FALSE);
00043
00044 CDC* pDC = GetDC();
00045 CFont* pOldFont = pDC->SelectObject(&m_font);
00046
00047
00048
00049 CString str(
00050 _T("This AVI file was not prepared for sequential reading, the alternative ")
00051 _T("'Avi Splitter' will now let the default one handle it. ")
00052 _T("The complete reinterleaving of this file is strongly recommended before ")
00053 _T("burning it onto a slow media like cd-rom."));
00054
00055 r = cr;
00056
00057 pDC->DrawText(str, r, DT_WORDBREAK|DT_CALCRECT);
00058 r.right = cr.right;
00059
00060 m_message.Create(str, WS_CHILD|WS_VISIBLE, r, this);
00061 m_message.SetFont(&m_font, FALSE);
00062
00063
00064
00065 r.SetRect(cr.left, r.bottom + 10, cr.right, cr.bottom);
00066
00067 str = _T("Do not show this dialog again (hold Shift to re-enable it)");
00068
00069 pDC->DrawText(str, r, DT_WORDBREAK|DT_CALCRECT);
00070 r.right = cr.right;
00071
00072 m_checkbox.Create(str, WS_CHILD|WS_VISIBLE|BS_CHECKBOX|BS_AUTOCHECKBOX, r, this, IDC_DONOTSHOWAGAINCHECK);
00073 m_checkbox.SetFont(&m_font, FALSE);
00074
00075 CheckDlgButton(IDC_DONOTSHOWAGAINCHECK, fHideChecked?BST_CHECKED:BST_UNCHECKED);
00076
00077
00078
00079 if(!fShowWarningText)
00080 {
00081 m_message.ShowWindow(SW_HIDE);
00082 m_checkbox.ShowWindow(SW_HIDE);
00083 r = cr;
00084 }
00085 else
00086 {
00087 r.SetRect(cr.left, r.bottom + 10, cr.right, cr.bottom);
00088 }
00089
00090 m_graph.Create(pAF, r, this);
00091
00092
00093
00094 pDC->SelectObject(pOldFont);
00095 ReleaseDC(pDC);
00096
00097 SetWindowPos(&wndTop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
00098 SetForegroundWindow();
00099 ShowWindow(SW_SHOWNORMAL);
00100
00101 return !!RunModalLoop();
00102 }
00103
00104 IMPLEMENT_DYNCREATE(CAviReportWnd, CWnd)
00105
00106 BEGIN_MESSAGE_MAP(CAviReportWnd, CWnd)
00107 ON_WM_CLOSE()
00108 ON_WM_MOUSEMOVE()
00109 END_MESSAGE_MAP()
00110
00111 void CAviReportWnd::OnClose()
00112 {
00113 EndModalLoop(IsDlgButtonChecked(IDC_DONOTSHOWAGAINCHECK));
00114 __super::OnClose();
00115 }
00116
00117 void CAviReportWnd::OnMouseMove(UINT nFlags, CPoint p)
00118 {
00119 MapWindowPoints(&m_graph, &p, 1);
00120
00121 CRect r, r2;
00122 m_graph.GetClientRect(r);
00123 r2 = r;
00124 r.bottom -= GRAPHFOOTER;
00125 r2.top = r.bottom;
00126
00127 if(r.PtInRect(p))
00128 {
00129 SetCapture();
00130
00131 int x = p.x - r.left;
00132 int y = r.bottom - p.y;
00133
00134 REFERENCE_TIME rt = m_rtDur * x / r.Width();
00135 int chunk = (int)(1.0 * m_nChunks * y / r.Height());
00136
00137 rt /= 10000;
00138 int ms = (int)(rt%1000);
00139 rt /= 1000;
00140 int s = (int)(rt%60);
00141 rt /= 60;
00142 int m = (int)(rt%60);
00143 rt /= 60;
00144 int h = (int)(rt);
00145
00146 CString str;
00147 str.Format(_T("%s (%d - %d:%02d:%02d.%03d)"), TITLE, chunk, h, m, s, ms);
00148 SetWindowText(str);
00149 }
00150 else if(r2.PtInRect(p))
00151 {
00152 SetCapture();
00153
00154 int dist = m_graph.GetChunkDist(p.x - r2.left);
00155 CString str;
00156 str.Format(_T("%s (chunk distance: %d"), TITLE, dist);
00157 if(dist >= 1000) str += _T(" - over the limit!");
00158 str += ")";
00159 SetWindowText(str);
00160 }
00161 else if(GetCapture() == this)
00162 {
00163 SetWindowText(TITLE);
00164
00165 ReleaseCapture();
00166 }
00167
00168 __super::OnMouseMove(nFlags, p);
00169 }
00170
00172
00173 CAviPlotterWnd::CAviPlotterWnd()
00174 {
00175 }
00176
00177 bool CAviPlotterWnd::Create(CAviFile* pAF, CRect r, CWnd* pParentWnd)
00178 {
00179 if(!CreateEx(WS_EX_CLIENTEDGE, _T("STATIC"), _T(""), WS_CHILD|WS_VISIBLE, r, pParentWnd, 0))
00180 return(false);
00181
00182 GetClientRect(r);
00183 int w = r.Width();
00184 int h = r.Height() - GRAPHFOOTER;
00185
00186 CDC* pDC = GetDC();
00187 m_dc.CreateCompatibleDC(pDC);
00188 m_bm.CreateCompatibleBitmap(pDC, r.Width(), r.Height());
00189 ReleaseDC(pDC);
00190
00191 CBitmap* pOldBitmap = m_dc.SelectObject(&m_bm);
00192
00193 m_dc.FillSolidRect(r, 0);
00194
00195 {
00196 CPen pen(PS_DOT, 1, 0x008000);
00197 CPen* pOldPen = m_dc.SelectObject(&pen);
00198 for(int y = 0, dy = max(h/10,1); y < h; y += dy) {if(y == 0) continue; m_dc.MoveTo(0, y); m_dc.LineTo(w, y);}
00199 for(int x = 0, dx = max(w/10,1); x < w; x += dx) {if(x == 0) continue; m_dc.MoveTo(x, 0); m_dc.LineTo(x, w);}
00200 m_dc.SelectObject(pOldPen);
00201 }
00202
00203 {
00204 CPen pen(PS_SOLID, 1, 0x00ff00);
00205 CPen* pOldPen = m_dc.SelectObject(&pen);
00206 m_dc.MoveTo(15, 30);
00207 m_dc.LineTo(15, 2);
00208 m_dc.LineTo(19, 10);
00209 m_dc.LineTo(11, 10);
00210 m_dc.LineTo(15, 2);
00211 m_dc.MoveTo(w-30-10, h-15);
00212 m_dc.LineTo(w-2-10, h-15);
00213 m_dc.LineTo(w-10-10, h-19);
00214 m_dc.LineTo(w-10-10, h-11);
00215 m_dc.LineTo(w-2-10, h-15);
00216 m_dc.SelectObject(pOldPen);
00217
00218 m_dc.SetTextColor(0x008000);
00219 m_dc.TextOut(20, 10, _T("Chunk"));
00220
00221 CSize size = m_dc.GetTextExtent(_T("Time"));
00222 m_dc.TextOut(w - size.cx - 10, h - size.cy - 20, _T("Time"));
00223 }
00224
00225 COLORREF clr[] = {0x0000ff,0xff0000,0x40ffff,0xff40ff,0xffff40,0xffffff};
00226
00227 for(int i = 0, y = 40, dy = m_dc.GetTextExtent(_T("Stream N")).cy + 1; i < (int)pAF->m_avih.dwStreams; i++, y += dy)
00228 {
00229 m_dc.SetTextColor(clr[i%pAF->m_avih.dwStreams]);
00230 m_dc.SetBkMode(TRANSPARENT);
00231 CString str;
00232 str.Format(_T("Stream %d"), i);
00233 m_dc.TextOut(10, y, str);
00234 }
00235
00236 DWORD nmax = 0, tmax = 0;
00237
00238 for(int i = 0; i < (int)pAF->m_avih.dwStreams; i++)
00239 {
00240 int cnt = pAF->m_strms[i]->cs2.GetCount();
00241 if(cnt <= 0) continue;
00242 CAviFile::strm_t::chunk2& c2 = pAF->m_strms[i]->cs2[cnt-1];
00243 nmax = max(nmax, c2.n);
00244 tmax = max(tmax, c2.t);
00245 }
00246
00247 if(nmax > 0 && tmax > 0)
00248 {
00249 CArray<CPen> pen;
00250 pen.SetSize(pAF->m_avih.dwStreams);
00251 for(int i = 0; i < pen.GetSize(); i++)
00252 pen[i].CreatePen(PS_SOLID, 2, clr[i]);
00253
00254 CArray<CPoint> pp;
00255 pp.SetSize(pAF->m_avih.dwStreams);
00256 for(int i = 0; i < pen.GetSize(); i++)
00257 pp[i].SetPoint(-1, -1);
00258
00259 m_chunkdist.SetSize(w);
00260 memset(m_chunkdist.GetData(), 0, sizeof(int)*w);
00261
00262 DWORD* curchunks = new DWORD[pAF->m_avih.dwStreams];
00263 memset(curchunks, 0, sizeof(DWORD)*pAF->m_avih.dwStreams);
00264
00265 CAviFile::strm_t::chunk2 cs2last = {-1, 0};
00266
00267 while(1)
00268 {
00269 CAviFile::strm_t::chunk2 cs2min = {LONG_MAX, LONG_MAX};
00270
00271 int n = -1;
00272 for(int i = 0; i < (int)pAF->m_avih.dwStreams; i++)
00273 {
00274 int curchunk = curchunks[i];
00275 if(curchunk >= pAF->m_strms[i]->cs2.GetSize()) continue;
00276 CAviFile::strm_t::chunk2& cs2 = pAF->m_strms[i]->cs2[curchunk];
00277 if(cs2.t < cs2min.t) {cs2min = cs2; n = i;}
00278 }
00279 if(n == -1) break;
00280
00281
00282 CPoint p;
00283 p.x = (int)(1.0 * w * cs2min.t / tmax);
00284 p.y = (int)(h - 1.0 * h * cs2min.n / nmax);
00285 if(pp[n] != p)
00286 {
00287 CPen* pOldPen = m_dc.SelectObject(&pen[n]);
00288 if(pp[n] == CPoint(-1, -1)) m_dc.MoveTo(p);
00289 else {m_dc.MoveTo(pp[n]); m_dc.LineTo(p);}
00290 m_dc.SelectObject(pOldPen);
00291 pp[n] = p;
00292 }
00293
00294 int dist = abs(cs2min.n - cs2last.n);
00295
00296 if(cs2last.t >= 0 )
00297 {
00298 if(p.x >= 0 && p.x < w)
00299 {
00300 m_chunkdist[p.x] = max(m_chunkdist[p.x], dist);
00301 }
00302 }
00303
00304 curchunks[n]++;
00305 cs2last = cs2min;
00306 }
00307
00308 CPen red(PS_SOLID, 1, 0x0000ff);
00309 CPen green(PS_SOLID, 1, 0x00ff00);
00310
00311 for(int x = 0; x < w; x++)
00312 {
00313 CPen* pOldPen = m_dc.SelectObject(m_chunkdist[x] >= 1000 ? &red : &green);
00314 m_dc.MoveTo(x, h);
00315 m_dc.LineTo(x, h + GRAPHFOOTER);
00316 m_dc.SelectObject(pOldPen);
00317 }
00318
00319 delete [] curchunks;
00320 }
00321
00322 m_dc.SelectObject(pOldBitmap);
00323
00324 return(true);
00325 }
00326
00327 IMPLEMENT_DYNCREATE(CAviPlotterWnd, CWnd)
00328
00329 BEGIN_MESSAGE_MAP(CAviPlotterWnd, CWnd)
00330 ON_WM_PAINT()
00331 END_MESSAGE_MAP()
00332
00333 void CAviPlotterWnd::OnPaint()
00334 {
00335 CPaintDC dc(this);
00336
00337 CRect r;
00338 GetClientRect(r);
00339
00340 CBitmap* pOld = m_dc.SelectObject(&m_bm);
00341 dc.BitBlt(0, 0, r.Width(), r.Height(), &m_dc, 0, 0, SRCCOPY);
00342 m_dc.SelectObject(pOld);
00343 }
00344