summaryrefslogtreecommitdiff
path: root/toxav/media.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxav/media.c')
-rw-r--r--toxav/media.c151
1 files changed, 32 insertions, 119 deletions
diff --git a/toxav/media.c b/toxav/media.c
index e18c1803..a327c751 100644
--- a/toxav/media.c
+++ b/toxav/media.c
@@ -28,13 +28,8 @@
28#endif /* HAVE_CONFIG_H */ 28#endif /* HAVE_CONFIG_H */
29 29
30#include <stdio.h> 30#include <stdio.h>
31#include <stdlib.h>
31#include <math.h> 32#include <math.h>
32#include <libavcodec/avcodec.h>
33#include <libavformat/avformat.h>
34#include <libswscale/swscale.h>
35#include <libavdevice/avdevice.h>
36#include <libavutil/opt.h>
37#include <opus/opus.h>
38#include <assert.h> 33#include <assert.h>
39 34
40#include "rtp.h" 35#include "rtp.h"
@@ -206,25 +201,11 @@ int queue(struct jitter_buffer *q, RTPMessage *pk)
206 201
207int init_video_decoder(CodecState *cs) 202int init_video_decoder(CodecState *cs)
208{ 203{
209 cs->video_decoder = avcodec_find_decoder(VIDEO_CODEC); 204 if (vpx_codec_dec_init_ver(&cs->v_decoder, VIDEO_CODEC_DECODER_INTERFACE, NULL, 0, VPX_DECODER_ABI_VERSION) != VPX_CODEC_OK) {
210
211 if (!cs->video_decoder) {
212 fprintf(stderr, "Init video_decoder failed!\n"); 205 fprintf(stderr, "Init video_decoder failed!\n");
213 return -1; 206 return -1;
214 } 207 }
215 208
216 cs->video_decoder_ctx = avcodec_alloc_context3(cs->video_decoder);
217
218 if (!cs->video_decoder_ctx) {
219 fprintf(stderr, "Init video_decoder_ctx failed!\n");
220 return -1;
221 }
222
223 if (avcodec_open2(cs->video_decoder_ctx, cs->video_decoder, NULL) < 0) {
224 fprintf(stderr, "Opening video decoder failed!\n");
225 return -1;
226 }
227
228 return 0; 209 return 0;
229} 210}
230 211
@@ -242,97 +223,32 @@ int init_audio_decoder(CodecState *cs, uint32_t audio_channels)
242} 223}
243 224
244 225
245int init_video_encoder(CodecState *cs, const char* webcam, const char* video_driver, uint32_t video_bitrate) 226int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t video_bitrate)
246{ 227{
247 cs->video_input_format = av_find_input_format(video_driver); 228 vpx_codec_enc_cfg_t cfg;
248 229 int res = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0);
249 if (avformat_open_input(&cs->video_format_ctx, webcam, cs->video_input_format, NULL) != 0) { 230 if(res) {
250 fprintf(stderr, "Opening video_input_format failed!\n"); 231 printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
251 return -1;
252 }
253
254 avformat_find_stream_info(cs->video_format_ctx, NULL);
255 av_dump_format(cs->video_format_ctx, 0, webcam, 0);
256
257 int i;
258
259 for (i = 0; i < cs->video_format_ctx->nb_streams; ++i) {
260 if (cs->video_format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
261 cs->video_stream = i;
262 break;
263 }
264 }
265
266 cs->webcam_decoder_ctx = cs->video_format_ctx->streams[cs->video_stream]->codec;
267 cs->webcam_decoder = avcodec_find_decoder(cs->webcam_decoder_ctx->codec_id);
268
269 if (cs->webcam_decoder == NULL) {
270 fprintf(stderr, "Unsupported codec!\n");
271 return -1;
272 }
273
274 if (cs->webcam_decoder_ctx == NULL) {
275 fprintf(stderr, "Init webcam_decoder_ctx failed!\n");
276 return -1;
277 }
278
279 if (avcodec_open2(cs->webcam_decoder_ctx, cs->webcam_decoder, NULL) < 0) {
280 fprintf(stderr, "Opening webcam decoder failed!\n");
281 return -1; 232 return -1;
282 } 233 }
283 234
284 cs->video_encoder = avcodec_find_encoder(VIDEO_CODEC); 235 cfg.rc_target_bitrate = video_bitrate;
285 236 cfg.g_w = width;
286 if (!cs->video_encoder) { 237 cfg.g_h = height;
287 fprintf(stderr, "Init video_encoder failed!\n"); 238 if(vpx_codec_enc_init_ver(&cs->v_encoder, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0, VPX_ENCODER_ABI_VERSION) != VPX_CODEC_OK) {
288 return -1; 239 fprintf(stderr, "Failed to initialize encoder\n");
289 }
290
291 cs->video_encoder_ctx = avcodec_alloc_context3(cs->video_encoder);
292
293 if (!cs->video_encoder_ctx) {
294 fprintf(stderr, "Init video_encoder_ctx failed!\n");
295 return -1;
296 }
297
298 cs->video_encoder_ctx->bit_rate = video_bitrate;
299 cs->video_encoder_ctx->rc_min_rate = cs->video_encoder_ctx->rc_max_rate = cs->video_encoder_ctx->bit_rate;
300 av_opt_set_double(cs->video_encoder_ctx->priv_data, "max-intra-rate", 90, 0);
301 av_opt_set(cs->video_encoder_ctx->priv_data, "quality", "realtime", 0);
302
303 cs->video_encoder_ctx->thread_count = 4;
304 cs->video_encoder_ctx->rc_buffer_aggressivity = 0.95;
305 cs->video_encoder_ctx->rc_buffer_size = video_bitrate * 6;
306 cs->video_encoder_ctx->profile = 3;
307 cs->video_encoder_ctx->qmax = 54;
308 cs->video_encoder_ctx->qmin = 4;
309 AVRational myrational = {1, 25};
310 cs->video_encoder_ctx->time_base = myrational;
311 cs->video_encoder_ctx->gop_size = 99999;
312 cs->video_encoder_ctx->pix_fmt = PIX_FMT_YUV420P;
313 cs->video_encoder_ctx->width = cs->webcam_decoder_ctx->width;
314 cs->video_encoder_ctx->height = cs->webcam_decoder_ctx->height;
315
316 if (avcodec_open2(cs->video_encoder_ctx, cs->video_encoder, NULL) < 0) {
317 fprintf(stderr, "Opening video encoder failed!\n");
318 return -1; 240 return -1;
319 } 241 }
320
321 return 0; 242 return 0;
322} 243}
323 244
324int init_audio_encoder(CodecState *cs) 245int init_audio_encoder(CodecState *cs, uint32_t audio_channels)
325{ 246{
326 int err = OPUS_OK; 247 int err = OPUS_OK;
327 cs->audio_encoder = opus_encoder_create(cs->audio_sample_rate, 1, OPUS_APPLICATION_VOIP, &err); 248 cs->audio_encoder = opus_encoder_create(cs->audio_sample_rate, audio_channels, OPUS_APPLICATION_AUDIO, &err);
328
329 err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(cs->audio_bitrate)); 249 err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(cs->audio_bitrate));
330 err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_COMPLEXITY(10)); 250 err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_COMPLEXITY(10));
331 err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE)); 251
332
333 /* NOTE: What do we do with this? */
334 int nfo;
335 err = opus_encoder_ctl(cs->audio_encoder, OPUS_GET_LOOKAHEAD(&nfo));
336 252
337 return err == OPUS_OK ? 0 : -1; 253 return err == OPUS_OK ? 0 : -1;
338} 254}
@@ -342,30 +258,26 @@ CodecState* codec_init_session ( uint32_t audio_bitrate,
342 uint16_t audio_frame_duration, 258 uint16_t audio_frame_duration,
343 uint32_t audio_sample_rate, 259 uint32_t audio_sample_rate,
344 uint32_t audio_channels, 260 uint32_t audio_channels,
345 uint32_t video_bitrate, 261 uint16_t video_width,
346 const char* webcam, 262 uint16_t video_height,
347 const char* webcam_driver ) 263 uint32_t video_bitrate )
348{ 264{
349 CodecState* _retu = av_calloc(sizeof(CodecState), 1); 265 CodecState* _retu = calloc(sizeof(CodecState), 1);
350 assert(_retu); 266 assert(_retu);
351 267
352
353 avdevice_register_all();
354 avcodec_register_all();
355 av_register_all();
356
357
358 _retu->audio_bitrate = audio_bitrate; 268 _retu->audio_bitrate = audio_bitrate;
359 _retu->audio_sample_rate = audio_sample_rate; 269 _retu->audio_sample_rate = audio_sample_rate;
360 270
361 pthread_mutex_init(&_retu->ctrl_mutex, NULL);
362
363
364 /* Encoders */ 271 /* Encoders */
365 if ( 0 == init_video_encoder(_retu, webcam, webcam_driver, video_bitrate) ) 272 if (!video_width || !video_height) {
273 video_width = 320;
274 video_height = 240;
275 }
276
277 if ( 0 == init_video_encoder(_retu, video_width, video_height, video_bitrate) )
366 printf("Video encoder initialized!\n"); 278 printf("Video encoder initialized!\n");
367 279
368 if ( 0 == init_audio_encoder(_retu) ) 280 if ( 0 == init_audio_encoder(_retu, audio_channels) )
369 printf("Audio encoder initialized!\n"); 281 printf("Audio encoder initialized!\n");
370 282
371 283
@@ -391,7 +303,8 @@ void codec_terminate_session ( CodecState* cs )
391 opus_decoder_destroy(cs->audio_decoder); 303 opus_decoder_destroy(cs->audio_decoder);
392 printf("Terminated decoder!\n"); 304 printf("Terminated decoder!\n");
393 } 305 }
394 306
395 /* TODO: Terminate video */ 307 /* TODO: Terminate video */
396 308 vpx_codec_destroy(&cs->v_decoder);
309 vpx_codec_destroy(&cs->v_encoder);
397} 310}