FreeRDP
Loading...
Searching...
No Matches
encoding.c
1
20#include <winpr/assert.h>
21#include <winpr/winpr.h>
22
23#include "camera.h"
24
25#define TAG CHANNELS_TAG("rdpecam-video.client")
26
32UINT32 h264_get_max_bitrate(UINT32 height)
33{
34 static struct Bitrates
35 {
36 UINT32 height;
37 UINT32 bitrate; /* kbps */
38
39 } bitrates[] = {
40 /* source: https://livekit.io/webrtc/bitrate-guide (webcam streaming)
41 *
42 * sorted by height in descending order
43 */
44 { 1080, 2700 }, { 720, 1250 }, { 480, 700 }, { 360, 400 },
45 { 240, 170 }, { 180, 140 }, { 0, 100 },
46 };
47 const size_t nBitrates = ARRAYSIZE(bitrates);
48
49 for (size_t i = 0; i < nBitrates; i++)
50 {
51 if (height >= bitrates[i].height)
52 {
53 UINT32 bitrate = bitrates[i].bitrate;
54 WLog_DBG(TAG, "Setting h264 max bitrate: %u kbps", bitrate);
55 return bitrate * 1000;
56 }
57 }
58
59 WINPR_ASSERT(FALSE);
60 return 0;
61}
62
68FREERDP_VIDEO_FORMAT ecamToVideoFormat(CAM_MEDIA_FORMAT ecamFormat)
69{
70 switch (ecamFormat)
71 {
72 case CAM_MEDIA_FORMAT_YUY2:
73 return FREERDP_VIDEO_FORMAT_YUYV422;
74 case CAM_MEDIA_FORMAT_NV12:
75 return FREERDP_VIDEO_FORMAT_NV12;
76 case CAM_MEDIA_FORMAT_I420:
77 return FREERDP_VIDEO_FORMAT_YUV420P;
78 case CAM_MEDIA_FORMAT_RGB24:
79 return FREERDP_VIDEO_FORMAT_RGB24;
80 case CAM_MEDIA_FORMAT_RGB32:
81 return FREERDP_VIDEO_FORMAT_RGB32;
82 case CAM_MEDIA_FORMAT_H264:
83 return FREERDP_VIDEO_FORMAT_H264;
84 case CAM_MEDIA_FORMAT_MJPG:
85 return FREERDP_VIDEO_FORMAT_MJPEG;
86 default:
87 WLog_ERR(TAG, "Unsupported ecamFormat %u", ecamFormat);
88 return FREERDP_VIDEO_FORMAT_NONE;
89 }
90}
91
98static BOOL ecam_init_video_context(CameraDeviceStream* stream)
99{
100 WINPR_ASSERT(stream);
101
102 if (stream->video)
103 return TRUE;
104
105 stream->video =
106 freerdp_video_context_new(stream->currMediaType.Width, stream->currMediaType.Height);
107 if (!stream->video)
108 {
109 WLog_ERR(TAG, "freerdp_video_context_new failed");
110 return FALSE;
111 }
112
113 return TRUE;
114}
115
121BOOL ecam_encoder_context_init(CameraDeviceStream* stream)
122{
123 if (!ecam_init_video_context(stream))
124 return FALSE;
125
126 const UINT32 framerate =
127 stream->currMediaType.FrameRateNumerator / stream->currMediaType.FrameRateDenominator;
128
129 if (!freerdp_video_context_reconfigure(stream->video, stream->currMediaType.Width,
130 stream->currMediaType.Height, framerate, 0,
131 H264_CAMERA_VIDEO_REAL_TIME))
132 {
133 WLog_ERR(TAG, "Failed to configure H.264 encoder");
134 return FALSE;
135 }
136
137 return TRUE;
138}
139
145BOOL ecam_encoder_context_free(CameraDeviceStream* stream)
146{
147 if (!stream)
148 return FALSE;
149
150 if (stream->video)
151 {
152 freerdp_video_context_free(stream->video);
153 stream->video = nullptr;
154 }
155
156 return TRUE;
157}
158
164BOOL ecam_encoder_compress(CameraDeviceStream* stream, const BYTE* srcData, size_t srcSize,
165 wStream* output)
166{
167 const FREERDP_VIDEO_FORMAT inputFormat = ecamToVideoFormat(streamInputFormat(stream));
168 const FREERDP_VIDEO_FORMAT outputFormat = ecamToVideoFormat(streamOutputFormat(stream));
169
170 if (!ecam_encoder_context_init(stream))
171 return FALSE;
172
173 return freerdp_video_sample_convert(stream->video, inputFormat, srcData, srcSize, outputFormat,
174 output);
175}