2

I am using libav (2.7 built for MSVC) to open a camera using dshow:

input_format = av_find_input_format("dshow");
avformat_open_input(format_context, "video=Integrated Camera", input_format, 0);

When I open the video stream it is "raw video" (according to its long_name) in the format AV_PIX_FMT_BGR24. I need to have frames in AV_PIX_FMT_RGB24 so I make a SwsContext as follows:

sws_context = sws_getContext(codec_context->width, codec_context->height, codec_context->pix_fmt, 
                             codec_context->width, codec_context->height, AV_PIX_FMT_RGB24,
                             SWS_BICUBIC, 0, 0, 0);
av_picture = new AVPicture();
avpicture_alloc(av_picture, AV_PIX_FMT_RGB24, codec_context->width, codec_context->height);

I then have a looping timer to read frames and decode into a AVFrame which is then passed off to sws_scale.

while(av_read_frame(format_context, &packet) >= 0)
{
  if(packet.stream_index == stream_index)
  {
    av_frame = 0;
    av_frame = av_frame_alloc();

    avcodec_decode_video2(codec_context, av_frame, &frame_finished, &packet);
    if(frame_finished)
    {
      sws_scale(sws_context, (const uint8_t * const *)av_frame->data, av_frame->linesize,
                0, codec_context->height, av_picture->data, av_picture->linesize);
      av_free_packet(&packet);
      return;
    }
  }
  av_free_packet(&packet);
}

After this point I would use av_picture in my application, however sws_scale hangs and crashes. Looking at all the data I am getting going into sws_scale nothing looks odd to me except the linesize for av_frame. av_frame->linesize[0] == -1920 (linesize[1] and linesize[2] are 0 as expected for BGR24). As the width of my frame is 640 I would expect 1920 but the negative sign seems very odd. I have tried flipping the sign but it does not help. I should note that it does not crash every time (some runs it makes it through a few frames first).

Why would the linesize be negative? Does it mean something or is it just screwed up somehow?

William Miller
  • 9,839
  • 3
  • 25
  • 46
Chris
  • 574
  • 7
  • 24
  • 2
    Is this to do with RGB being bottom up? So the negative sign indicates the line pitch? https://msdn.microsoft.com/en-us/library/windows/desktop/dd407212(v=vs.85).aspx – EdChum Apr 08 '16 at 15:54
  • Wouldn't a negative linesize correspond with a negative biWidth (which they do not discuss) as opposed to a negative biHeight (which they do)? – Chris Apr 08 '16 at 16:04

1 Answers1

2

Standard RGB line ordering in Windows for bitmaps and video is bottom-to-top (AFAIR it's only relatively fresh APIs like WIC and Direct2D where line are reordered the natural way). Top-to-bottom order of lines is indicated by negative height and is basically rare. There is nothing wrong with this line order, the pointer to "first pixel" points to leftmost pixel of last row and then you advance between rows by negative offset. libswscale handles this fine.

Wouldn't a negative linesize correspond with a negative biWidth (which they do not discuss) as opposed to a negative biHeight (which they do)?

No, the convention is this: if biHeight is negative then it's minus the number of lines and the order of lines is reversed. biWidth is always positive (biWidth is responsible to carry another extension: it might be enlarged to indicated non-standard extended stride in case there is padding to the right from the the payload image).

Roman R.
  • 68,205
  • 6
  • 94
  • 158
  • Thanks for the explanation! Any ideas of what I should be looking for to figure out why sws_scale is crashing? – Chris Apr 08 '16 at 16:51
  • I would start with inspecting crash point. Whether it's read or write of swscale planes. Compare to arguments of the call, perhaps memory access is outside of intended boundaries, then you will clarify why exactly. – Roman R. Apr 08 '16 at 16:56
  • I get a read access violation in for src rgb24tobgr24_c (rgb2rgb_template.c). It originates from bad memory in the srcSlice array passed into sws_scale (av_frame->data). To me this indicates decode isn't filling out av_frame correctly (or maybe read frame is doing something bad to packet). Is there a good way to follow back where this originates? – Chris Apr 08 '16 at 19:28