| 369 | } |
| 370 | |
| 371 | bool JPEGVideo::encodeData(const QImage& image,uint32_t /* size_hint */,RsVOIPDataChunk& voip_chunk) |
| 372 | { |
| 373 | // check if we make a diff image, or if we use the full frame. |
| 374 | |
| 375 | QImage encoded_frame ; |
| 376 | bool differential_frame ; |
| 377 | |
| 378 | if (_encoded_ref_frame_count++ < _encoded_ref_frame_max_distance |
| 379 | && image.size() == _encoded_reference_frame.size() |
| 380 | && image.byteCount() == _encoded_reference_frame.byteCount()) |
| 381 | { |
| 382 | // compute difference with reference frame. |
| 383 | encoded_frame = image ; |
| 384 | |
| 385 | for(int i=0;i<image.byteCount();++i) |
| 386 | { |
| 387 | // We cannot use basic modulo 256 arithmetic, because the decompressed JPeg frames do not follow the same rules (values are clamped) |
| 388 | // and cause color blotches when perturbated by a differential frame. |
| 389 | |
| 390 | int diff = ( (int)image.bits()[i] - (int)_encoded_reference_frame.bits()[i]) + 128; |
| 391 | encoded_frame.bits()[i] = (unsigned char)std::max(0,std::min(255,diff)) ; |
| 392 | } |
| 393 | |
| 394 | differential_frame = true ; |
| 395 | } |
| 396 | else |
| 397 | { |
| 398 | _encoded_ref_frame_count = 0 ; |
| 399 | _encoded_reference_frame = image.copy() ; |
| 400 | encoded_frame = image ; |
| 401 | |
| 402 | differential_frame = false ; |
| 403 | } |
| 404 | |
| 405 | QByteArray qb ; |
| 406 | |
| 407 | QBuffer buffer(&qb) ; |
| 408 | buffer.open(QIODevice::WriteOnly) ; |
| 409 | encoded_frame.save(&buffer,"JPEG") ; |
| 410 | |
| 411 | voip_chunk.data = rs_malloc(HEADER_SIZE + qb.size()); |
| 412 | |
| 413 | if(!voip_chunk.data) |
| 414 | return false ; |
| 415 | |
| 416 | // build header |
| 417 | uint32_t flags = differential_frame ? JPEG_VIDEO_FLAGS_DIFFERENTIAL_FRAME : 0x0 ; |
| 418 | |
| 419 | ((unsigned char *)voip_chunk.data)[0] = VideoProcessor::VIDEO_PROCESSOR_CODEC_ID_JPEG_VIDEO & 0xff ; |
| 420 | ((unsigned char *)voip_chunk.data)[1] = (VideoProcessor::VIDEO_PROCESSOR_CODEC_ID_JPEG_VIDEO >> 8) & 0xff ; |
| 421 | ((unsigned char *)voip_chunk.data)[2] = flags & 0xff ; |
| 422 | ((unsigned char *)voip_chunk.data)[3] = (flags >> 8) & 0xff ; |
| 423 | |
| 424 | memcpy(&((unsigned char*)voip_chunk.data)[HEADER_SIZE],qb.data(),qb.size()) ; |
| 425 | |
| 426 | voip_chunk.size = HEADER_SIZE + qb.size() ; |
| 427 | voip_chunk.type = RsVOIPDataChunk::RS_VOIP_DATA_TYPE_VIDEO ; |
| 428 |
no test coverage detected