c++ - Broken output from libavcodec/swscale, depending on resolution -


i writing video conference software, have h.264 stream decoded libavcoded iyuv , rendered window vmr9 in windowless mode. use directshow graph so.

to avoid unnecessary conversion rgb , (see link), convert iyuv video yuy2 before passing vmr9, libswscale.

i noticed video resolution of 848x480, output video broken, investigated further , came resolutions video broken. exclude libswscale elaboration, added support iyuv+padding iyuv conversion, , worked, resolutions.

still, willing avoid slow iyuv, implemented support nv12 (with libswscale) , yv12 (manually, same iyuv). after doing tests on 2 different computers, came strange results.

resolution  yuy2    nv12    iyuv    yv12 pc 1 (my laptop)                 640x360     ok      broken  ok      broken 848x480     broken  broken  ok      broken 960x540     broken  broken  ok      broken 1024x576    ok      ok      ok      ok 1280x720    ok      ok      ok      broken 1920x1080   ok      broken  ok      broken  pc 2                 640x360     ok      ok      ok      ok 848x480     ok      broken  ok      broken 960x540     ok      ok      ok      ok 1024x576    ok      ok      ok      ok 1280x720    ok      broken  ok      ok 1920x1080   ok      ok      ok      ok 

to exclude vmr9 fault, substituted evr, same results.

i know padding needed memory alignment, , size of padding depends on cpu used (libavcodec doc), may explain difference between 2 computers(first has intel i7-3820qm, second intel core 2 quad q6600). suppose has padding, because images corrupted in way. you can see blue t-shirt in lower part of image. can see blue t-shirt in lower part of image, , face in upper one.

to follow code conversion. nv12 , yuy2 conversions performed libswscale, while iyuv , yv12 manually.

int pixels = _outputframe->width * _outputframe->height; if (_outputformat == "yuy2") {     int stride = _outputframe->width * 2;     sws_scale(_convertctx, _outputframe->data, _outputframe->linesize, 0, _outputframe->height, &out, &stride); } else if (_outputformat == "nv12") {     int stride[] = { _outputframe->width, _outputframe->width };     uint8_t * dst[] = { out, out + pixels };     sws_scale(_convertctx, _outputframe->data, _outputframe->linesize, 0, _outputframe->height, dst, stride); } else if (_outputformat == "iyuv") { // clean ffmpeg padding     (int = 0; < _outputframe->height; i++) // copy y         memcpy(out + * _outputframe->width, _outputframe->data[0] + * _outputframe->linesize[0] , _outputframe->width);     (int = 0; < _outputframe->height / 2; i++) // copy u         memcpy(out + pixels + * _outputframe->width / 2, _outputframe->data[1] + * _outputframe->linesize[1] , _outputframe->width / 2);                 (int = 0; < _outputframe->height / 2; i++) // copy v         memcpy(out + pixels + pixels/4 + * _outputframe->width / 2, _outputframe->data[2] + * _outputframe->linesize[2] , _outputframe->width / 2); }  else if (_outputformat == "yv12") { // iyuv, u inverted v plane     (int = 0; < _outputframe->height; i++) // copy y         memcpy(out + * _outputframe->width, _outputframe->data[0] + * _outputframe->linesize[0], _outputframe->width);     (int = 0; < _outputframe->height / 2; i++) // copy v         memcpy(out + pixels + * _outputframe->width / 2, _outputframe->data[2] + * _outputframe->linesize[2], _outputframe->width / 2);     (int = 0; < _outputframe->height / 2; i++) // copy u         memcpy(out + pixels + pixels / 4 + * _outputframe->width / 2, _outputframe->data[1] + * _outputframe->linesize[1], _outputframe->width / 2); } 

out output buffer. _outputframe libavcodec output avframe. _convertctx initialized follows.

if (_outputformat == "yuy2")     _convertctx = sws_getcontext(_width, _height, av_pix_fmt_yuv420p,                                  _width, _height, av_pix_fmt_yuyv422, sws_fast_bilinear, nullptr, nullptr, nullptr); else if (_outputformat == "nv12")     _convertctx = sws_getcontext(_width, _height, av_pix_fmt_yuv420p,                                  _width, _height, av_pix_fmt_nv12, sws_fast_bilinear, nullptr, nullptr, nullptr); 

questions:

  1. are manual conversions correct?
  2. are assumptions correct?
  3. is previous 2 answers positive, problem? , especially...
  4. why presents resolutions , not others?
  5. what additional info can provide?


Comments

Popular posts from this blog

commonjs - How to write a typescript definition file for a node module that exports a function? -

openid - Okta: Failed to get authorization code through API call -

thorough guide for profiling racket code -