Я использую libav (2.7 построен для MSVC), чтобы открыть камеру с помощью dshow:
input_format = av_find_input_format("dshow");
avformat_open_input(format_context, "video=Integrated Camera", input_format, 0);
Когда я открываю видеопоток, это «сырое видео» (в соответствии с его длинным именем) в формате AV_PIX_FMT_BGR24. Мне нужно иметь кадры в AV_PIX_FMT_RGB24, поэтому я делаю SwsContext следующим образом:
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);
Затем у меня есть циклический таймер для чтения кадров и декодирования в AVFrame, который затем передается в 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);
}
После этого я буду использовать av_picture в своем приложении, однако sws_scale зависает и вылетает. Глядя на все данные, которые я получаю в sws_scale, для меня нет ничего странного, кроме linesize для av_frame. av_frame->linsize[0] == -1920
(размеры линий 1 и 2 равны 0, как и ожидалось для BGR24). Поскольку ширина моей рамки равна 640, я ожидал бы 1920, но отрицательный знак кажется очень странным. Я попытался перевернуть знак, но это не помогает. Я должен отметить, что он не падает каждый раз (при некоторых запусках он сначала проходит несколько кадров).
Почему размер линии будет отрицательным? Это что-то значит или просто облажалось?
Стандартное упорядочение строк RGB в Windows для растровых изображений и видео — снизу вверх (AFAIR — это только относительно новые API, такие как WIC и Direct2D, где линии переупорядочены естественным образом). Порядок линий сверху вниз обозначается отрицательной высотой и в основном встречается редко. В этом порядке строк нет ничего плохого: указатель на «первый пиксель» указывает на крайний левый пиксель последней строки, а затем вы перемещаетесь между строками с отрицательным смещением. libswscale
справляется с этим нормально.
Разве отрицательный размер линии не будет соответствовать отрицательному значению biWidth (которое они не обсуждают), а не отрицательному значению biHeight (которое они делают)?
Нет, соглашение таково: если biHeight
отрицательно, то это минус количество строк и порядок строк меняется на противоположный. biWidth
всегда положительно (biWidth
несет ответственность за перенос другого расширения: оно может быть увеличено до указанного нестандартного расширенного шага в случае заполнения справа от изображения полезной нагрузки).
Других решений пока нет …