#ffmpeg #rgb #cairo #libav #libavcodec
#ffmpeg #rgb #каир #libav #libavcodec
Вопрос:
Я должен заполнить ffmpeg AVFrame-> данные из данных пикселя поверхности cairo. У меня есть этот код:
/* Image info and pixel data */
width = cairo_image_surface_get_width( surface );
height = cairo_image_surface_get_height( surface );
stride = cairo_image_surface_get_stride( surface );
pix = cairo_image_surface_get_data( surface );
for( row = 0; row < height; row )
{
data = pix row * stride;
for( col = 0; col < width; col )
{
img->video_frame->data[0][row * img->video_frame->linesize[0] col] = data[0];
img->video_frame->data[1][row * img->video_frame->linesize[1] col] = data[1];
//img->video_frame->data[2][row * img->video_frame->linesize[2] col] = data[2];
data = 4;
}
img->video_frame->pts ;
}
Но цвета в экспортированном видео неправильные. Исходное сердце красного цвета. Может кто-нибудь указать мне правильное направление? К сожалению, пример encode.c бесполезен, и в Интернете много путаницы в отношении Y, Cr и Cb, которые я действительно не понимаю. Пожалуйста, не стесняйтесь запрашивать более подробную информацию. Большое спасибо.
Комментарии:
1. Не могли бы вы опубликовать полный пример кода — что-то, что мы можем скомпилировать и выполнить? Возможно, вам придется проявить творческий подход — рассмотрите возможность размещения входного изображения размером 8×8 в виде массива C (инициализированного кодом). Можете ли вы описать расположение данных
pix
(является ли это основным RGBA строки сwidth
,height
иstride
)? В какой части используется формат пикселей YCbCr?2. Большое спасибо за ответ. Я действительно ценю. Код является частью графического интерфейса GTK3, который превращает серию изображений в фильм. Это проект, который я разрабатываю с 2009 года. К сожалению, я не могу предоставить фрагмент кода, но программное обеспечение с открытым исходным кодом. Поверхность cairo — RGB24. Контекст AV создается как AV_PIX_FMT_YUV420P, потому что, если я использую AV_PIX_FMT_RGB24, я получаю сообщение об ошибке во время завершения: «Ширина ввода больше шага». Надеюсь, это поможет, пожалуйста, не стесняйтесь запрашивать дополнительную информацию.
3. Мое текущее понимание YCbCr заключается в том, что он состоит из яркости / красного / синего, где яркость — это яркость, а красный и синий — это значения цветности с информацией о красном / зеленом и синем / зеленом соответственно. Это работает путем объединения черно-белого изображения с двумя каналами цветности
Ответ №1:
Необходимо использовать libswscale
для преобразования исходных данных изображения из RGB24
YUV420P
в.
Что-то вроде:
int width = cairo_image_surface_get_width( surface );
int height = cairo_image_surface_get_height( surface );
int stride = cairo_image_surface_get_stride( surface );
uint8_t *pix = cairo_image_surface_get_data( surface );
uint8_t *data[1] = { pix };
int linesize[1] = { stride };
struct SwsContext *sws_ctx = sws_getContext(width, height, AV_PIX_FMT_RGB24 ,
width, height, AV_PIX_FMT_YUV420P,
SWS_BILINEAR, NULL, NULL, NULL);
sws_scale(sws_ctx, data, linesize, 0, height,
img->video_frame->data, img->video_frame->linesize);
sws_freeContext(sws_ctx);
Смотрите пример здесь: scaling_video
Комментарии:
1. Спасибо за ваш ответ. Я также использовал sws_scale, ошибок во время кодирования не было, но видео даже не воспроизводилось, а VLC показывает кучу этих бесполезных сообщений в окне терминала: [h264 @ 0x7f1508c82700] совместно расположенные POCs недоступны [h264 @ 0x7f1508c9f400] mmco: короткий сбой unref [h264 @ 0x7f1508cd8f80] совместно расположенные POCs недоступныпример не помог, поскольку он конвертируется ИЗ YUV420P, но спасибо, я оценил это. Если вы хотите узнать больше, я могу внести изменения на сервер SVN, и вы можете посмотреть, это хороший графический интерфейс и хорошее программное обеспечение, просто, к сожалению, недооцененное.
2. @GiuTor Не могли бы вы сбросить образец изображения cairo в файл где-нибудь и опубликовать формат, ширину и высоту?
3. корректен ли этот код для сброса изображения: /* Информация об изображении и пиксельные данные */ width = cairo_image_surface_get_width(поверхность); height = cairo_image_surface_get_height(поверхность); stride = cairo_image_surface_get_stride(поверхность); pix = cairo_image_surface_get_data(поверхность); FILE * fp = fopen(«cairo_image.raw» , «w»); fwrite (pix, 4 *width, sizeof(pix), fp); fclose(fp);