#include "rtp-ext.h"
#include <inttypes.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>

// https://www.arib.or.jp/english/html/overview/doc/STD-T63V12_00/5_Appendix/Rel13/26/26114-d30.pdf
/*
7.4.5 Coordination of Video Orientation
Coordination of Video Orientation consists in signalling of the current orientation of the image captured on the sender
side to the receiver for appropriate rendering and displaying. When CVO is succesfully negotiated it shall be signalled
by the MTSI client. The signalling of the CVO uses RTP Header Extensions as specified in IETF RFC 5285 [95]. The
one-byte form of the header should be used. CVO information for a 2 bit granularity of Rotation (corresponding to
urn:3gpp:video-orientation) is carried as a byte formatted as follows:
    0                   1
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  ID   | len=0 |0 0 0 0 C F R R|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

	Bit#		7 6 5 4 3 2 1  0(LSB)
	Definition  0 0 0 0 C F R1 R0

With the following definitions:
C = Camera: indicates the direction of the camera used for this video stream. It can be used by the MTSI client in
    receiver to e.g. display the received video differently depending on the source camera.
	0: Front-facing camera, facing the user. If camera direction is unknown by the sending MTSI client in the terminal then this is the default value used.
	1: Back-facing camera, facing away from the user.
F = Flip: indicates a horizontal (left-right flip) mirror operation on the video as sent on the link.
	0: No flip operation. If the sending MTSI client in terminal does not know if a horizontal mirror operation is necessary, then this is the default value used.
	1: Horizontal flip operation
R1, R0 = Rotation: indicates the rotation of the video as transmitted on the link. The receiver should rotate the video to
	compensate that rotation. E.g. a 90กใ Counter Clockwise rotation should be compensated by the receiver with a 90กใ
	Clockwise rotation prior to displaying.

Table 7.2: Rotation signalling for 2 bit granularity
R1 R0 Rotation of the video as sent on the link		Rotation on the receiver before display
0  0	0กใ rotation									None
0  1	90กใ Counter Clockwise (CCW) rotation or		90กใ CW rotation
		270กใ Clockwise (CW) rotation
1  0	180กใ CCW rotation or 180กใ CW rotation		180กใ CW rotation
1  1	270กใ CCW rotation or 90กใ CW rotation		90กใ CCW rotation

CVO information for a higher granularity of Rotation (corresponding to urn:3GPP:video-orientation:6) is carried as a
byte formatted as follows:
	Bit#       7   6  5  4 3 2  1 0(LSB)
	Definition R5 R4 R3 R2 C F R1 R0

where C and F are as defined above and the bits R5,R4,R3,R2,R1,R0 represent the Rotation, which indicates the
rotation of the video as transmitted on the link. Table 7.3 describes the rotation to be applied by the receiver based on
the rotation bits.

Table 7.3: Rotation signalling for 6 bit granularity
R1	R0	R5	R4	R3	R2	Rotation of the video as		Rotation on the receiver 
						sent on the link				before display
0	0	0	0	0	0	0กใ rotation						None
0	0	0	0	0	1	(360/64)กใ Counter Clockwise		(360/64)กใ CW rotation
						(CCW) rotation
0	0	0	0	1	0	(2*360/64)กใ CCW rotation		(2*360/64)กใ CW rotation
.	.	.	.	.	.	.								.
.	.	.	.	.	.	.								.
.	.	.	.	.	.	.								.
1	1	1	1	1	0	(62*360/64)กใ CCW rotation		(2*360/64)กใ CCW rotation
1	1	1	1	1	1	(63*360/64)กใ CCW rotation		(360/64)กใ CCW rotation
*/

int rtp_ext_video_orientation_parse(const uint8_t* data, int bytes, struct rtp_ext_video_orientation_t *ext)
{
	assert(1 == bytes);
	if (bytes < 1)
		return -1;

	ext->camera = (data[0] >> 3) & 0x01;
	ext->flip = (data[0] >> 2) & 0x01;
	ext->rotaion = (data[0] & 0x03) * 90;
	return 0;
}

int rtp_ext_video_orientation_write(uint8_t* data, int bytes, const struct rtp_ext_video_orientation_t* ext)
{
	if (bytes < 1)
		return -1;
	
	data[0] = ext->camera ? 0x04 : 0;
	data[0] |= ext->flip ? 0x03 : 0;
	data[0] |= (ext->rotaion / 90) & 0x03;
	return 1;
}
