Skip to content

Instantly share code, notes, and snippets.

@i-rinat
Created July 5, 2014 17:43
Show Gist options
  • Save i-rinat/286f5d7322e80464d888 to your computer and use it in GitHub Desktop.
Save i-rinat/286f5d7322e80464d888 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
extern "C" {
#include <libswscale/swscale.h>
}
#include <libyuv.h>
#define WIDTH 1366
#define STRIDE 1376
#define HEIGHT 768
#define FRAMES 8000
void
Convert_BGRA_YUV420_SSSE3(unsigned int w, unsigned int h, const uint8_t* in_data, int in_stride,
uint8_t* const out_data[3], const int out_stride[3]);
uint8_t bgra_buf[STRIDE * HEIGHT * 4];
uint8_t out_y[STRIDE * HEIGHT];
uint8_t out_u[STRIDE * HEIGHT / 4];
uint8_t out_v[STRIDE * HEIGHT / 4];
void
prepare_bgra_buf(void)
{
memset(bgra_buf, 0, sizeof(bgra_buf));
for (int k = 0; k < HEIGHT; k ++) {
for (int j = 0; j < WIDTH; j ++) {
bgra_buf[4 * (k * STRIDE + j) + 0] = rand() & 0xff;
bgra_buf[4 * (k * STRIDE + j) + 1] = rand() & 0xff;
bgra_buf[4 * (k * STRIDE + j) + 2] = rand() & 0xff;
bgra_buf[4 * (k * STRIDE + j) + 3] = 0;
}
}
}
double
elapsed(struct timespec t_start, struct timespec t_end)
{
return (t_end.tv_sec - t_start.tv_sec) + 1e-9 * (t_end.tv_nsec - t_start.tv_nsec);
};
int
main(void)
{
printf("benchmarking ssr yuv converter\n");
srand(43);
prepare_bgra_buf();
struct timespec t_start, t_end;
// ssr's Convert_BGRA_YUV420_SSSE3
clock_gettime(CLOCK_MONOTONIC, &t_start);
for (int k = 0; k < FRAMES; k ++) {
uint8_t* const out_data[4] = {out_y, out_u, out_v, NULL};
const int out_stride[4] = {STRIDE, STRIDE/2, STRIDE/2, 0};
Convert_BGRA_YUV420_SSSE3(WIDTH, HEIGHT, bgra_buf, STRIDE, out_data, out_stride);
}
clock_gettime(CLOCK_MONOTONIC, &t_end);
printf("ssr %.1f fps\n", FRAMES / elapsed(t_start, t_end));
// libswscale
struct SwsContext *sc = NULL;
clock_gettime(CLOCK_MONOTONIC, &t_start);
for (int k = 0; k < FRAMES; k ++) {
uint8_t* const out_data[4] = {out_y, out_u, out_v, NULL};
const int out_stride[4] = {STRIDE, STRIDE/2, STRIDE/2, 0};
sc = sws_getCachedContext(sc,
WIDTH, HEIGHT, AV_PIX_FMT_BGRA,
WIDTH, HEIGHT, AV_PIX_FMT_YUV420P,
SWS_POINT,
NULL, NULL, NULL);
uint8_t *const srcSlice[4] = {bgra_buf, NULL, NULL, NULL};
const int srcStride[4] = {STRIDE, 0, 0, 0};
sws_scale(sc, srcSlice, srcStride, 0, HEIGHT, out_data, out_stride);
}
clock_gettime(CLOCK_MONOTONIC, &t_end);
printf("swscale %.1f fps\n", FRAMES / elapsed(t_start, t_end));
// libswscale reverse (YUV420P -> BGRA)
clock_gettime(CLOCK_MONOTONIC, &t_start);
for (int k = 0; k < FRAMES; k ++) {
uint8_t* const out_data[4] = {out_y, out_u, out_v, NULL};
const int out_stride[4] = {STRIDE, STRIDE/2, STRIDE/2, 0};
sc = sws_getCachedContext(sc,
WIDTH, HEIGHT, AV_PIX_FMT_YUV420P,
WIDTH, HEIGHT, AV_PIX_FMT_BGRA,
SWS_POINT,
NULL, NULL, NULL);
uint8_t *const srcSlice[4] = {bgra_buf, NULL, NULL, NULL};
const int srcStride[4] = {STRIDE, 0, 0, 0};
sws_scale(sc, out_data, out_stride, 0, HEIGHT, srcSlice, srcStride);
}
clock_gettime(CLOCK_MONOTONIC, &t_end);
printf("swscale rev %.1f fps\n", FRAMES / elapsed(t_start, t_end));
// libyuv
clock_gettime(CLOCK_MONOTONIC, &t_start);
for (int k = 0; k < FRAMES; k ++) {
uint8_t* const out_data[4] = {out_y, out_u, out_v, NULL};
const int out_stride[4] = {STRIDE, STRIDE/2, STRIDE/2, 0};
uint8_t *const srcSlice[4] = {bgra_buf, NULL, NULL, NULL};
const int srcStride[4] = {STRIDE, 0, 0, 0};
libyuv::BGRAToI420(bgra_buf, STRIDE * 4,
out_y, STRIDE,
out_v, STRIDE/2,
out_u, STRIDE/2,
WIDTH, HEIGHT);
}
clock_gettime(CLOCK_MONOTONIC, &t_end);
printf("libyuv %.1f fps\n", FRAMES / elapsed(t_start, t_end));
printf("done\n");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment