void VideoSourceCanvas::Grabber(void *data) { nsresult rv; PRUint32 wr; VideoSourceCanvas *vs = static_cast<VideoSourceCanvas*>(data); int isize = vs->GetFrameSize(); int fsize = vs->width * vs->height * 4; char *i420 = (char *)PR_Calloc(isize, 1); PRUint8 *rgb32 = (PRUint8 *)PR_Calloc(fsize, 1); PRTime epoch_c; PRFloat64 epoch; PRIntervalTime ticks = PR_TicksPerSecond() / 30; while (vs->running) { PR_Sleep(ticks); if (vs->is_rec == PR_FALSE) continue; rv = vs->vCanvas->GetImageData_explicit( 0, 0, vs->width, vs->height, rgb32, fsize ); if (NS_FAILED(rv)) continue; RGB32toI420(vs->width, vs->height, (const char *)rgb32, i420); epoch_c = PR_Now(); epoch = (PRFloat64)(epoch_c / MICROSECONDS); epoch += ((PRFloat64)(epoch_c % MICROSECONDS)) / MICROSECONDS; rv = vs->output->Write((const char *)&epoch, sizeof(PRFloat64), &wr); rv = vs->output->Write((const char *)&isize, sizeof(PRUint32), &wr); rv = vs->output->Write((const char *)i420, isize, &wr); } PR_Free(i420); PR_Free(rgb32); return; }
STDMETHODIMP VideoSourceWin::SampleCB(double Time, IMediaSample *pSample) { HRESULT hr; nsresult rv; PRUint32 wr; BYTE *pBuffer; long bufferLen; PRUint8 *i420buf; int start, end, fsize, isize, bpp; bpp = 4; fsize = width * height * 4; isize = width * height * 3 / 2; bufferLen = pSample->GetActualDataLength(); hr = pSample->GetPointer(&pBuffer); nsAutoArrayPtr<PRUint8> rgb32(new PRUint8[bufferLen]); memcpy(rgb32.get(), pBuffer, bufferLen); pBuffer = rgb32.get(); /* Reverse RGB32 top-down */ PRUint8 tmp; for (start = 0, end = bufferLen - bpp; start < bufferLen / 2; start += bpp, end -= bpp) { /* While we're here let's do a RGB<->BGR swap */ tmp = pBuffer[start]; pBuffer[start] = pBuffer[end+2]; pBuffer[end+2] = tmp; tmp = pBuffer[start+1]; pBuffer[start+1] = pBuffer[end+1]; pBuffer[end+1] = tmp; tmp = pBuffer[start+2]; pBuffer[start+2] = pBuffer[end]; pBuffer[end] = tmp; tmp = pBuffer[start+3]; pBuffer[start+3] = pBuffer[end+3]; pBuffer[end+3] = tmp; } /* Write header: timestamp + length */ if (is_rec != PR_TRUE) return S_OK; //PRFloat64 current = epoch + Time; PRTime epoch_c = PR_Now(); PRFloat64 epoch = (PRFloat64)(epoch_c / MICROSECONDS); epoch += ((PRFloat64)(epoch_c % MICROSECONDS)) / MICROSECONDS; rv = output->Write( (const char *)&epoch, sizeof(PRFloat64), &wr ); rv = output->Write( (const char *)&isize, sizeof(PRUint32), &wr ); /* Write to pipe after converting to i420 */ i420buf = (PRUint8 *)PR_Calloc(isize, sizeof(PRUint8)); RGB32toI420(width, height, (const char *)pBuffer, (char *)i420buf); rv = output->Write((const char *)i420buf, isize, &wr); PR_Free(i420buf); /* Write sample to canvas if neccessary */ if (vCanvas) { nsCOMPtr<nsIRunnable> render = new CanvasRenderer( vCanvas, width, height, rgb32, fsize ); rv = NS_DispatchToMainThread(render); } rgb32 = NULL; // AutoPtr should free this? return S_OK; }
STDMETHODIMP VideoSourceWinCallback::SampleCB(double Time, IMediaSample *pSample) { HRESULT hr; nsresult rv; PRUint32 wr; BYTE *pBuffer; long bufferLen; PRUint8 *i420buf; int start, end, fsize, isize, bpp; bpp = 4; fsize = w * h * 4; isize = w * h * 3 / 2; bufferLen = pSample->GetActualDataLength(); hr = pSample->GetPointer(&pBuffer); nsAutoArrayPtr<PRUint8> rgb32(new PRUint8[bufferLen]); memcpy(rgb32.get(), pBuffer, bufferLen); pBuffer = rgb32.get(); /* Reverse RGB32 top-down */ PRUint8 tmp; for (start = 0, end = bufferLen - bpp; start < bufferLen / 2; start += bpp, end -= bpp) { /* While we're here let's do a RGB<->BGR swap */ tmp = pBuffer[start]; pBuffer[start] = pBuffer[end+2]; pBuffer[end+2] = tmp; tmp = pBuffer[start+1]; pBuffer[start+1] = pBuffer[end+1]; pBuffer[end+1] = tmp; tmp = pBuffer[start+2]; pBuffer[start+2] = pBuffer[end]; pBuffer[end] = tmp; tmp = pBuffer[start+3]; pBuffer[start+3] = pBuffer[end+3]; pBuffer[end+3] = tmp; } /* Write sample to canvas if neccessary */ if (vCanvas) { nsCOMPtr<nsIRunnable> render = new CanvasRenderer( vCanvas, w, h, rgb32, fsize ); rv = NS_DispatchToMainThread(render); } /* Write to pipe after converting to i420 */ i420buf = (PRUint8 *)PR_Calloc(isize, sizeof(PRUint8)); RGB32toI420(w, h, (const char *)pBuffer, (char *)i420buf); rv = output->Write((const char *)i420buf, isize, &wr); PR_Free(i420buf); return S_OK; }