00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef VIDEO_VIDEOFRAME_C_DEFINED
00039 #define VIDEO_VIDEOFRAME_C_DEFINED
00040
00041 #include "Video/VideoFrame.H"
00042
00043 #include "Image/Image.H"
00044 #include "Image/Pixels.H"
00045 #include "Util/StringUtil.H"
00046 #include "Util/log.H"
00047 #include "Util/sformat.H"
00048 #include "Video/RgbConversion.H"
00049 #include "rutz/mappedfile.h"
00050 #include "rutz/shared_ptr.h"
00051 #include "rutz/trace.h"
00052 #include "Raster/DeBayer.H"
00053
00054 #include <fcntl.h>
00055 #include <istream>
00056 #include <sys/mman.h>
00057 #include <sys/stat.h>
00058 #include <sys/types.h>
00059 #include <unistd.h>
00060 #include <vector>
00061
00062
00063 namespace
00064 {
00065 void checkDataLength(const size_t actualLength,
00066 const VideoFormat mode,
00067 const Dims& dims,
00068 const bool strict)
00069 {
00070 const size_t expectedLength = getFrameSize(mode, dims);
00071
00072 if (actualLength == expectedLength)
00073
00074 return;
00075
00076
00077
00078 if(mode == VIDFMT_MJPEG) return;
00079
00080
00081
00082
00083
00084 uint numer = 0, denom = 0;
00085 getBytesPerPixelForMode(mode, &numer, &denom);
00086 ASSERT(numer > 0);
00087 ASSERT(denom > 0);
00088
00089 const size_t numPix = (actualLength * denom) / numer;
00090
00091 const uint aspects[][2] =
00092 {
00093
00094
00095
00096 { 4, 3 },
00097 { 16, 9 },
00098 { 1, 1 },
00099
00100
00101 { 0, 0 }
00102 };
00103
00104 std::string suggestion;
00105
00106 for (size_t i = 0; aspects[i][0] > 0; ++i)
00107 {
00108 const uint aw = aspects[i][0];
00109 const uint ah = aspects[i][1];
00110
00111
00112
00113
00114
00115
00116
00117 const uint wsq = (numPix*aw)/ah;
00118
00119 const uint w = uint(sqrt(double(wsq)));
00120 const uint h = (w*ah)/aw;
00121
00122
00123
00124
00125 if (w*w == wsq && w*h == numPix)
00126 {
00127 if (suggestion.length() == 0)
00128 suggestion = "\n\tpossible matching frame sizes include:";
00129
00130 suggestion += sformat("\n\t\t%ux%u (%ux%u aspect)",
00131 w, h, aw, ah);
00132 }
00133 }
00134
00135 if (actualLength < expectedLength)
00136 LFATAL("VideoFrame buffer is too small for %dx%d mode %s\n"
00137 "\t(expected %"ZU" bytes, got %"ZU" bytes)%s",
00138 dims.w(), dims.h(), convertToString(mode).c_str(),
00139 expectedLength, actualLength, suggestion.c_str());
00140
00141 if (actualLength > expectedLength)
00142 {
00143
00144
00145
00146
00147
00148 const std::string msg =
00149 sformat("VideoFrame buffer is larger than expected for %dx%d mode %s\n"
00150 "\t(expected %"ZU" bytes, got %"ZU" bytes; you should\n"
00151 "\tdouble-check the width and height settings on your\n"
00152 "\tframegrabber, mpeg file, etc. or try --yuv-dims)%s",
00153 dims.w(), dims.h(), convertToString(mode).c_str(),
00154 expectedLength, actualLength, suggestion.c_str());
00155
00156 if (strict)
00157 LFATAL("%s", msg.c_str());
00158 else
00159 LDEBUG("%s", msg.c_str());
00160 }
00161 }
00162
00163 template <class T>
00164 class ArrayHandleStorage : public VideoFrame::Storage
00165 {
00166 public:
00167 ArrayHandleStorage(const ArrayHandle<T>& hdl) : itsHdl(hdl) {}
00168
00169 virtual ~ArrayHandleStorage() {}
00170
00171 virtual Storage* clone() const
00172 {
00173
00174 return new ArrayHandleStorage<T>(this->itsHdl);
00175 }
00176
00177 ArrayHandle<T> itsHdl;
00178 };
00179
00180 template <class T>
00181 class ImageStorage : public VideoFrame::Storage
00182 {
00183 public:
00184 ImageStorage(const Image<T>& img) : itsImg(img) {}
00185
00186 virtual ~ImageStorage() {}
00187
00188 virtual Storage* clone() const
00189 {
00190
00191 return new ImageStorage<T>(this->itsImg);
00192 }
00193
00194 Image<T> itsImg;
00195 };
00196
00197 class MappedFileStorage : public VideoFrame::Storage
00198 {
00199 public:
00200 MappedFileStorage(rutz::shared_ptr<rutz::mapped_infile> f) : itsFile(f) {}
00201
00202 virtual ~MappedFileStorage() {}
00203
00204 virtual Storage* clone() const
00205 {
00206 return new MappedFileStorage(this->itsFile);
00207 }
00208
00209 rutz::shared_ptr<rutz::mapped_infile> itsFile;
00210 };
00211 }
00212
00213
00214 VideoFrame::Storage::~Storage() {}
00215
00216
00217 VideoFrame::VideoFrame()
00218 :
00219 itsStorage(),
00220 itsData(0),
00221 itsDims(),
00222 itsMode(VIDFMT_AUTO),
00223 itsByteSwap(false)
00224 {
00225 GVX_TRACE(__PRETTY_FUNCTION__);
00226 }
00227
00228
00229 VideoFrame::VideoFrame(const byte* data, const size_t length, const Dims& dims,
00230 const VideoFormat mode, const bool byteswap,
00231 const bool strictLength)
00232 :
00233 itsStorage(),
00234 itsData(data),
00235 itsDataLength(length),
00236 itsDims(dims),
00237 itsMode(mode),
00238 itsByteSwap(byteswap)
00239 {
00240 GVX_TRACE(__PRETTY_FUNCTION__);
00241 checkDataLength(itsDataLength, itsMode, itsDims, strictLength);
00242 }
00243
00244
00245
00246 VideoFrame::VideoFrame(const ArrayHandle<byte>& hdl, const Dims& dims,
00247 const VideoFormat mode, const bool byteswap)
00248 :
00249 itsStorage(new ArrayHandleStorage<byte>(hdl)),
00250 itsData(hdl.get().data()),
00251 itsDataLength(hdl.get().dims().sz()),
00252 itsDims(dims),
00253 itsMode(mode),
00254 itsByteSwap(byteswap)
00255 {
00256 GVX_TRACE(__PRETTY_FUNCTION__);
00257 checkDataLength(itsDataLength, itsMode, itsDims, true);
00258 }
00259
00260
00261 VideoFrame::VideoFrame(const Image<byte>& gray)
00262 :
00263 itsStorage(new ImageStorage<byte>(gray)),
00264 itsData(gray.getArrayPtr()),
00265 itsDataLength(gray.getSize() * sizeof(byte)),
00266 itsDims(gray.getDims()),
00267 itsMode(VIDFMT_GREY),
00268 itsByteSwap(false)
00269 {
00270 GVX_TRACE(__PRETTY_FUNCTION__);
00271 checkDataLength(itsDataLength, itsMode, itsDims, true);
00272 }
00273
00274
00275 VideoFrame::VideoFrame(const Image<PixRGB<byte> >& rgb)
00276 :
00277 itsStorage(new ImageStorage<PixRGB<byte> >(rgb)),
00278 itsData(reinterpret_cast<const byte*>(rgb.getArrayPtr())),
00279 itsDataLength(rgb.getSize() * sizeof(PixRGB<byte>)),
00280 itsDims(rgb.getDims()),
00281 itsMode(VIDFMT_RGB24),
00282 itsByteSwap(false)
00283 {
00284 GVX_TRACE(__PRETTY_FUNCTION__);
00285 ASSERT(sizeof(PixRGB<byte>) == 3);
00286 checkDataLength(itsDataLength, itsMode, itsDims, true);
00287 }
00288
00289
00290 VideoFrame::VideoFrame(const Image<PixVideoYUV<byte> >& yuv)
00291 :
00292 itsStorage(new ImageStorage<PixVideoYUV<byte> >(yuv)),
00293 itsData(reinterpret_cast<const byte*>(yuv.getArrayPtr())),
00294 itsDataLength(yuv.getSize() * sizeof(PixVideoYUV<byte>)),
00295 itsDims(yuv.getDims()),
00296 itsMode(VIDFMT_YUV24),
00297 itsByteSwap(false)
00298 {
00299 GVX_TRACE(__PRETTY_FUNCTION__);
00300 ASSERT(sizeof(PixVideoYUV<byte>) == 3);
00301 checkDataLength(itsDataLength, itsMode, itsDims, true);
00302 }
00303
00304
00305 VideoFrame::~VideoFrame()
00306 {
00307 GVX_TRACE(__PRETTY_FUNCTION__);
00308 }
00309
00310
00311 VideoFrame::VideoFrame(const VideoFrame& that)
00312 :
00313 itsStorage(that.itsStorage.get()
00314 ? that.itsStorage->clone()
00315 : 0),
00316 itsData(that.itsData),
00317 itsDataLength(that.itsDataLength),
00318 itsDims(that.itsDims),
00319 itsMode(that.itsMode),
00320 itsByteSwap(that.itsByteSwap)
00321 {
00322 GVX_TRACE(__PRETTY_FUNCTION__);
00323 }
00324
00325
00326 VideoFrame& VideoFrame::operator=(const VideoFrame& that)
00327 {
00328 GVX_TRACE(__PRETTY_FUNCTION__);
00329
00330 itsStorage.reset(that.itsStorage.get()
00331 ? that.itsStorage->clone()
00332 : 0);
00333 itsData = that.itsData;
00334 itsDataLength = that.itsDataLength;
00335 itsDims = that.itsDims;
00336 itsMode = that.itsMode;
00337 itsByteSwap = that.itsByteSwap;
00338
00339 return *this;
00340 }
00341
00342
00343 VideoFrame VideoFrame::fromFile(const char* fname, const Dims& dims,
00344 const VideoFormat mode,
00345 const bool byteswap,
00346 const bool strict)
00347 {
00348 rutz::shared_ptr<rutz::mapped_infile> fmap(new rutz::mapped_infile(fname));
00349
00350 VideoFrame result;
00351 result.itsStorage.reset(new MappedFileStorage(fmap));
00352 result.itsData = static_cast<const byte*>(fmap->memory());
00353 result.itsDataLength = fmap->length();
00354 result.itsDims = dims;
00355 result.itsMode = mode;
00356 result.itsByteSwap = byteswap;
00357
00358 checkDataLength(result.itsDataLength, result.itsMode, result.itsDims,
00359 strict);
00360
00361 return result;
00362 }
00363
00364
00365 VideoFrame VideoFrame::fromStream(std::istream& strm,
00366 const Dims& dims,
00367 const VideoFormat mode,
00368 const bool byteswap,
00369 const bool fail_is_fatal)
00370 {
00371 const size_t sz = getFrameSize(mode, dims);
00372
00373 ArrayHandle<byte> data
00374 (new ArrayData<byte>(Dims(sz, 1), NO_INIT));
00375
00376 strm.read(reinterpret_cast<char*>(data.uniq().dataw()), sz);
00377
00378 if (strm.fail())
00379 {
00380 if (fail_is_fatal)
00381 LFATAL("error while reading data from input stream");
00382 else
00383 return VideoFrame();
00384 }
00385
00386 return VideoFrame(data, dims, mode, byteswap);
00387 }
00388
00389
00390 VideoFrame VideoFrame::deepCopyOf(const VideoFrame& original)
00391 {
00392 GVX_TRACE(__PRETTY_FUNCTION__);
00393
00394 if (!original.initialized())
00395
00396
00397 return VideoFrame();
00398
00399 if (original.itsStorage.get() != 0)
00400
00401
00402 return original;
00403
00404
00405
00406 ArrayHandle<byte> newhdl
00407 (new ArrayData<byte>(Dims(original.getBufSize(), 1),
00408 original.itsData));
00409
00410 return VideoFrame(newhdl, original.itsDims, original.itsMode,
00411 original.itsByteSwap);
00412 }
00413
00414
00415 size_t VideoFrame::getBufSize() const
00416 {
00417 GVX_TRACE(__PRETTY_FUNCTION__);
00418
00419 const size_t expectedLength = getFrameSize(itsMode, itsDims);
00420
00421 if(expectedLength <= 0) return itsDataLength;
00422
00423
00424
00425
00426 ASSERT(itsDataLength >= expectedLength);
00427
00428
00429
00430
00431
00432
00433
00434 ASSERT(itsData != 0 || expectedLength == 0);
00435
00436 return expectedLength;
00437 }
00438
00439
00440 namespace
00441 {
00442 void bobDeinterlace(const byte* src, const byte* const srcend,
00443 byte* dest, byte* const destend,
00444 const int height, const int stride,
00445 const bool in_bottom_field)
00446 {
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 ASSERT(height > 0);
00470 ASSERT(stride > 0);
00471
00472
00473
00474
00475
00476 #if 1
00477 # define DOCOPY(dst,src,n) std::copy((src),(src)+(n),(dst))
00478 #else
00479 # define DOCOPY(dst,src,n) memcpy((dst),(src),(n))
00480 #endif
00481
00482 if (in_bottom_field)
00483 {
00484 src += stride;
00485
00486 DOCOPY(dest, src, stride);
00487
00488 dest += stride;
00489 }
00490
00491 DOCOPY(dest, src, stride);
00492
00493 dest += stride;
00494
00495 const int N = (height / 2) - 1;
00496 for (int i = 0; i < N; ++i)
00497 {
00498 const byte* const src2 = src + (stride*2);
00499
00500 for (int k = 0; k < stride; ++k)
00501 dest[k] = (src[k] + src2[k]) / 2;
00502
00503 dest += stride;
00504
00505 DOCOPY(dest, src2, stride);
00506
00507 src += stride*2;
00508 dest += stride;
00509 }
00510
00511 if (!in_bottom_field)
00512 {
00513 DOCOPY(dest, src, stride);
00514
00515 src += stride*2;
00516 dest += stride;
00517 }
00518 else
00519 src += stride;
00520
00521
00522
00523 if (src != srcend)
00524 LFATAL("deinterlacing consistency check failed: %d src %p-%p=%d",
00525 int(in_bottom_field), src, srcend, int(src-srcend));
00526
00527 if (dest != destend)
00528 LFATAL("deinterlacing consistency check failed: %d dst %p-%p=%d",
00529 int(in_bottom_field), dest, destend, int(dest-destend));
00530 }
00531
00532 #undef DOCOPY
00533
00534 }
00535
00536
00537 VideoFrame VideoFrame::makeBobDeinterlaced(int in_bottom_field) const
00538 {
00539 GVX_TRACE(__PRETTY_FUNCTION__);
00540
00541
00542
00543
00544
00545
00546 ArrayHandle<byte> hdl
00547 (new ArrayData<byte>(Dims(getFrameSize(itsMode, itsDims), 1),
00548 NO_INIT));
00549
00550 byte* const dest = hdl.uniq().dataw();
00551 const byte* const src = this->getBuffer();
00552 const int w = this->getDims().w();
00553 const int h = this->getDims().h();
00554 const int stride = getScanlineWidth(this->getMode(), w);
00555
00556 if (stride > 0)
00557 {
00558 bobDeinterlace(src, src+h*stride, dest, dest+h*stride,
00559 h, stride, in_bottom_field);
00560 }
00561 else if (this->getMode() == VIDFMT_YUV420P)
00562 {
00563
00564
00565
00566
00567 bobDeinterlace(src, src+w*h, dest, dest+w*h,
00568 h, w, in_bottom_field);
00569
00570
00571
00572
00573 const int w2 = (w+1)/2;
00574 const int h2 = (h+1)/2;
00575
00576
00577 bobDeinterlace(src + w*h, src + w*h + w2*h2,
00578 dest + w*h, dest + w*h + w2*h2,
00579 h2, w2, in_bottom_field);
00580
00581 bobDeinterlace(src + w*h + w2*h2, src + w*h + 2*w2*h2,
00582 dest + w*h + w2*h2, dest + w*h + 2*w2*h2,
00583 h2, w2, in_bottom_field);
00584 }
00585
00586 return VideoFrame(hdl, this->getDims(), this->getMode(),
00587 this->getByteSwap());
00588 }
00589
00590
00591 VideoFrame VideoFrame::getFlippedHoriz() const
00592 {
00593 GVX_TRACE(__PRETTY_FUNCTION__);
00594
00595
00596 if (this->getMode() != VIDFMT_YUV420P)
00597 LFATAL("Sorry, only VIDFMT_YUV420P is currently supported");
00598
00599
00600 ArrayHandle<byte> hdl
00601 (new ArrayData<byte>(Dims(getFrameSize(itsMode, itsDims), 1), NO_INIT));
00602
00603 byte* dest = hdl.uniq().dataw();
00604 const byte* src = this->getBuffer();
00605 const int w = this->getDims().w();
00606 const int h = this->getDims().h();
00607
00608 const byte *ysrc = src;
00609 const byte *usrc = ysrc + w * h;
00610 const byte *vsrc = usrc + ((w+1)/2) * ((h+1)/2);
00611
00612
00613 for (int j = 0; j < h; j ++)
00614 for (int i = 0; i < w; i ++)
00615 *dest++ = ysrc[(j+1)*w - i - 1];
00616
00617
00618 for (int j = 0; j < (h+1)/2; j ++)
00619 for (int i = 0; i < (w+1)/2; i ++)
00620 *dest++ = usrc[(j+1)*((w+1)/2) - i - 1];
00621
00622 for (int j = 0; j < (h+1)/2; j ++)
00623 for (int i = 0; i < (w+1)/2; i ++)
00624 *dest++ = vsrc[(j+1)*((w+1)/2) - i - 1];
00625
00626 return VideoFrame(hdl, this->getDims(), VIDFMT_YUV420P, this->getByteSwap());
00627 }
00628
00629
00630 namespace
00631 {
00632 std::string extensionFor(const Dims& dims, VideoFormat mode)
00633 {
00634 return sformat(".%dx%d.%s",
00635 dims.w(), dims.h(),
00636 toLowerCase(convertToString(mode)).c_str());
00637 }
00638
00639 std::string addExtension(const char* fstem,
00640 const Dims& dims, VideoFormat mode)
00641 {
00642 const std::string ext = extensionFor(dims, mode);
00643
00644 std::string result(fstem);
00645
00646 if (result.size() < ext.size() ||
00647 result.compare(result.size() - ext.size(), result.npos,
00648 ext) != 0)
00649 result += ext;
00650
00651 ASSERT(result.compare(result.size() - ext.size(), result.npos,
00652 ext) == 0);
00653
00654 return result;
00655 }
00656 }
00657
00658
00659 std::string VideoFrame::diskDumpMmap(const char* fstem, bool flush) const
00660 {
00661 GVX_TRACE(__PRETTY_FUNCTION__);
00662
00663 const std::string fname = addExtension(fstem, itsDims, itsMode);
00664
00665 const int fd =
00666 open(fname.c_str(),
00667 O_CREAT | O_RDWR | O_TRUNC,
00668 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
00669
00670 if (fd == -1)
00671 PLFATAL("Cannot open %s for writing", fname.c_str());
00672
00673 const size_t siz = this->getBufSize();
00674
00675 if (siz != 0)
00676 {
00677
00678
00679 lseek(fd, siz-1, SEEK_SET);
00680 int ret = write(fd, "", 1);
00681 ASSERT(ret > 0);
00682 lseek(fd, 0, SEEK_SET);
00683
00684 void* const mem = mmap(0, siz, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
00685 if (mem == MAP_FAILED)
00686 { close(fd); PLFATAL("mmap() failed for %s", fname.c_str()); }
00687
00688 memcpy(mem, this->getBuffer(), siz);
00689
00690 if (munmap(mem, siz) != 0)
00691 { close(fd); PLFATAL("munmap() failed for %s", fname.c_str()); }
00692 }
00693
00694 if (flush)
00695 fsync(fd);
00696
00697 close(fd);
00698
00699 return fname;
00700 }
00701
00702
00703 std::string VideoFrame::diskDumpStdio(const char* fstem, bool flush) const
00704 {
00705 GVX_TRACE(__PRETTY_FUNCTION__);
00706
00707 const std::string fname = addExtension(fstem, itsDims, itsMode);
00708
00709 const int fd =
00710 open(fname.c_str(),
00711 O_CREAT | O_RDWR | O_TRUNC,
00712 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
00713
00714 if (fd == -1)
00715 PLFATAL("Cannot open %s for writing", fname.c_str());
00716
00717 const size_t siz = this->getBufSize();
00718
00719 if (write(fd, this->getBuffer(), siz) != ssize_t(siz))
00720 { close(fd); PLFATAL("write() failed for %s", fname.c_str()); }
00721
00722 if (flush)
00723 fsync(fd);
00724
00725 close(fd);
00726
00727 return fname;
00728 }
00729
00730
00731 Image<PixRGB<byte> > VideoFrame::toRgb() const
00732 {
00733 GVX_TRACE(__PRETTY_FUNCTION__);
00734
00735 if (itsData == 0)
00736 LFATAL("Eeek! I have no data!");
00737
00738
00739
00740 const byte* d = itsData;
00741 const size_t s = this->getBufSize();
00742 const Dims m = itsDims;
00743 const bool p = itsByteSwap;
00744
00745 switch (itsMode)
00746 {
00747 case VIDFMT_GREY: return fromMono (d,s,m);
00748 case VIDFMT_RGB555: return fromRGB555 (d,s,m,p);
00749 case VIDFMT_RGB565: return fromRGB565 (d,s,m,p);
00750 case VIDFMT_RGB24: return fromRGB (d,s,m,p);
00751 case VIDFMT_RGB32: return fromARGB (d,s,m,p);
00752 case VIDFMT_YUV24: return fromVideoYUV24 (d,s,m,p);
00753 case VIDFMT_UYVY: return fromVideoYUV422 (d,s,m,p);
00754 case VIDFMT_YUYV: return fromVideoYUV422 (d,s,m,!p);
00755 case VIDFMT_YUV444: return fromVideoYUV444 (d,s,m,p);
00756 case VIDFMT_YUV422: return fromVideoYUV422 (d,s,m,p);
00757 case VIDFMT_YUV411: return fromVideoYUV411 (d,s,m,p);
00758 case VIDFMT_YUV420: return fromVideoYUV420P (d,s,m);
00759 case VIDFMT_YUV410: return fromVideoYUV410P (d,s,m);
00760 case VIDFMT_YUV444P: return fromVideoYUV444P (d,s,m);
00761 case VIDFMT_YUV422P: return fromVideoYUV422P (d,s,m);
00762 case VIDFMT_YUV411P: return fromVideoYUV411P (d,s,m);
00763 case VIDFMT_YUV420P: return fromVideoYUV420P (d,s,m);
00764 case VIDFMT_YUV410P: return fromVideoYUV410P (d,s,m);
00765 case VIDFMT_HM12: return fromVideoHM12 (d,s,m);
00766 case VIDFMT_MJPEG: return fromVideoMJPEG (d,s,m);
00767 case VIDFMT_BAYER_GB: return fromBayer(d,s,m, BAYER_GBRG);
00768 case VIDFMT_BAYER_BG: return fromBayer(d,s,m, BAYER_BGGR);
00769 case VIDFMT_BAYER_GR: return fromBayer(d,s,m, BAYER_GRBG);
00770 case VIDFMT_BAYER_RG: return fromBayer(d,s,m, BAYER_RGGB);
00771 default:
00772 LFATAL("Sorry, conversion from selected grabmode to RGB not implemented!");
00773 }
00774 return Image< PixRGB<byte> >();
00775 }
00776
00777
00778 Image<PixRGB<uint16> > VideoFrame::toRgbU16() const
00779 {
00780 GVX_TRACE(__PRETTY_FUNCTION__);
00781
00782 if (itsData == 0)
00783 LFATAL("Eeek! I have no data!");
00784
00785
00786
00787 const uint16* d = (uint16*)itsData;
00788
00789 const size_t s = this->getBufSize();
00790 const Dims m = itsDims;
00791
00792 switch (itsMode)
00793 {
00794 case VIDFMT_BAYER_GB12: return fromBayerU16 (d,s,m, BAYER_GBRG12);
00795 case VIDFMT_BAYER_BG12: return fromBayerU16 (d,s,m, BAYER_BGGR12);
00796 case VIDFMT_BAYER_GR12: return fromBayerU16 (d,s,m, BAYER_GRBG12);
00797 case VIDFMT_BAYER_RG12: return fromBayerU16 (d,s,m, BAYER_RGGB12);
00798 default:
00799 LFATAL("Sorry, conversion from selected grabmode to RGB not implemented!");
00800 }
00801 return Image< PixRGB<uint16> >();
00802 }
00803
00804
00805 void VideoFrame::toYuvComponents(Image<byte>& y,
00806 Image<byte>& u,
00807 Image<byte>& v) const
00808 {
00809 const byte* buf = this->getBuffer();
00810 const Dims dims = this->getDims();
00811
00812 switch (this->getMode())
00813 {
00814 case VIDFMT_YUV420P:
00815 y = Image<byte>(buf, dims);
00816 u = Image<byte>(buf + dims.sz(), (dims + 1) / 2);
00817 v = Image<byte>(buf + dims.sz() + ((dims + 1) / 2).sz(),
00818 (dims + 1) / 2);
00819 break;
00820
00821
00822
00823 default:
00824 LFATAL("toYuvComponents() not supported for VideoFormat %s",
00825 convertToString(this->getMode()).c_str());
00826 }
00827 }
00828
00829
00830
00831
00832
00833
00834
00835
00836 #endif // VIDEO_VIDEOFRAME_C_DEFINED