本次推视频流从摄像头拿到的数据是RGB32的,在编码推流后,播放器播放出来是倒置的画面。
需要对原始数据进行数据倒转处理。如下
1 struct Rgb32Byte
2 {
3 uint8_t r;
4 uint8_t g;
5 uint8_t b;
6 uint8_t a;
7 };
8
9 void VideoReadThread::RGB32ToYUV420P(unsigned char *src, unsigned char *dst, int Width, int height)
10 {
11 //解决图像倒置问题
12 Rgb32Byte *reb32Buf = (Rgb32Byte *)src;
13 std::reverse(reb32Buf, reb32Buf + Width*height);
14
15 unsigned char * dst_y_even;
16 unsigned char * dst_y_odd;
17 unsigned char * dst_u;
18 unsigned char * dst_v;
19 const unsigned char *src_even;
20 const unsigned char *src_odd;
21
22 int i, j;
23 src_even = (const unsigned char *)reb32Buf;
24 src_odd = src_even + Width * 4;
25 // it's planar
26
27 dst_y_even = (unsigned char *)dst;
28 dst_y_odd = dst_y_even + Width;
29 dst_u = dst_y_even + Width * height;
30 dst_v = dst_u + ((Width * height) >> 2);
31 // NB this doesn't work perfectly for u and v values of theedges of the video if your video size is not divisible by 2.FWIW.
32
33 for (i = 0; i < height / 2; ++i) {
34 for (j = 0; j < Width / 2; ++j) {
35 short r, g, b;
36 b = *src_even++;
37 g = *src_even++;
38 r = *src_even++;
39 ++src_even;
40 *dst_y_even++ = ((r * 66 + g * 129 + b * 25 + 128) >> 8) + 16;
41
42 short sum_r = r, sum_g = g, sum_b = b;
43 b = *src_even++;
44 g = *src_even++;
45 r = *src_even++;
46 ++src_even;
47 *dst_y_even++ = ((r * 66 + g * 129 + b * 25 + 128) >> 8) + 16;
48
49 sum_r += r;
50 sum_g += g;
51 sum_b += b;
52
53 b = *src_odd++;
54 g = *src_odd++;
55 r = *src_odd++;
56 ++src_odd;
57 *dst_y_odd++ = ((r * 66 + g * 129 + b * 25 + 128) >> 8) + 16;
58
59 sum_r += r;
60 sum_g += g;
61 sum_b += b;
62 b = *src_odd++;
63 g = *src_odd++;
64 r = *src_odd++;
65 ++src_odd;
66 *dst_y_odd++ = ((r * 66 + g * 129 + b * 25 + 128) >> 8) + 16;
67 sum_r += r;
68 sum_g += g;
69 sum_b += b;
70
71 // compute ave's of this 2x2 bloc for its u and v values
72 // could use Catmull-Rom interpolation possibly?
73 //http://msdn.microsoft.com/en-us/library/Aa904813#yuvformats_420formats_16bitsperpixel
74 // rounding by one? don't care enough... 39 ms - 36.8
75 //sum_r += 2;
76 //sum_g += 2;
77 //sum_b += 2;
78 // divide by 4 to average
79 sum_r /= 4;
80 sum_g /= 4;
81 sum_b /= 4;
82 *dst_u++ = ((sum_r * -38 - sum_g * 74 + sum_b * 112 + 128) >> 8) + 128; // only one
83 *dst_v++ = ((sum_r * 112 - sum_g * 94 - sum_b * 18 + 128) >> 8) + 128; // only one
84 }
85 dst_y_even += Width;
86 dst_y_odd += Width;
87 src_even += Width * 4;
88 src_odd += Width * 4;
89 }
90 }