//
//  YCKVideoFrameContext.h
//  YCKit
//
//  Created by 徐家骏 on 2019/5/7.
//  Copyright © 2019 徐家骏. All rights reserved.
//
#pragma once
#ifndef YCKIT_YCKIT_VIDEO_YCKVIDEOFRAMECONTEXT_H_
#define YCKIT_YCKIT_VIDEO_YCKVIDEOFRAMECONTEXT_H_
#include <memory>
#ifdef SDK_SIMPLE_INCLUDE
#include "common.h"
#include "YCKitExport.h"
#else
#include <YCKSdwan/common.h>
#include <YCKit/YCKitExport.h>
#endif
#include "NVVideoTransformMeta.h"
/*16bit的attribute:
1、是否i帧
2、是否前置摄像头
3、是否已有镜像（android）
45、设备的方向
67、摄像头的方向
8、图片是否只解码不实际渲染
9-16：扩展用
*/

//关于设备方向、摄像头方向、mirror。属性是从移动设备定义过来的。详细说明见本文件尾部。
enum DLL_DECL YCKVideoExtraAttribute
{
	EXTRA_ATTR_IFRAME = 1,
	EXTRA_ATTR_FRONT_CAMERA = 2,
	EXTRA_ATTR_MIRRORED = 4,
	EXTRA_ATTR_DEVICE_ORIENT_PORTRAIT = 0,
	EXTRA_ATTR_DEVICE_ORIENT_PORTRAIT_UP = 8,
	EXTRA_ATTR_DEVICE_ORIENT_LANDSCAPE_LEFT = 16,
	EXTRA_ATTR_DEVICE_ORIENT_LANDSCAPE_RIGHT = 24,
	EXTRA_ATTR_CAMERA_ORIENT_PORTRAIT = 0,
	EXTRA_ATTR_CAMERA_ORIENT_PORTRAIT_UP = 32,
	EXTRA_ATTR_CAMERA_ORIENT_LANDSCAPE_LEFT = 64,
	EXTRA_ATTR_CAMERA_ORIENT_LANDSCAPE_RIGHT = 96,
	EXTRA_ATTR_NOT_RENDER_TO_SCREEN = 128,
};

class DLL_DECL YCKVideoFrameContext
{
public:
	PROPERTY(nonatomic) uint16_t attribute;
	PROPERTY(nonatomic) int16_t audioSeqId;
	PROPERTY(nonatomic) int16_t timestamp;

	//本地使用
	PROPERTY(nonatomic) BOOL forLocalPreview;
	//本地使用
	int64_t				real_timestamp;
	//本地使用。由解码器设置其值
	bool				is_iOS;
	//本地使用。移动端保存在VideoEngine里。使用dataEngine告知变化
	std::shared_ptr<NVVideoTransformMeta> transformMeta;
public:
	YCKVideoFrameContext();
	~YCKVideoFrameContext();

	/**
	 * setting device orientation by VideoEngine inline function (getDeviceOrientationFlag)
	 */
	void setFlag(uint16_t flag);
	BOOL isIFrame() const;
	BOOL isFrontCamera() const;
	uint16_t deviceOrientation() const;
	uint16_t cameraOrientation() const;
	BOOL flagNotRenderToScreen() const;
	BOOL isMirrored() const;
private:

public:
#ifndef SDK_SIMPLE_INCLUDE
	static std::shared_ptr<YCKVideoFrameContext> initWithData(shared_const_buffer data);
	shared_const_buffer toData();
#endif
};

/**
 *
 * By dengminhao
 * 设备方向：将设备正常竖立，与站着的持有这个设备的人（你自己）平行放置。设备顶部（或者说头部）向上放置为默认值（ORIENT_PORTRAIT）。
 * 这个可以用顶部摄像头作为标识（或者其他可以识别设备顶部和尾部的标识）。那么，将设备顺时针旋转90度，180度，270度分别为
 * ORIENT_LANDSCAPE_RIGHT（注意这里右边指的是持有设备的人的右边，不是设备的右边），
 * ORIENT_PORTRAIT_UP（这里定义这个enum的家骏省略了，应该是UP_DOWN，即顶部朝下的意思），
 * ORIENT_LANDSCAPE_LEFT (顶部水平朝左。一样这里是指朝向持有这个设备的人的左边）
 * 简单示意：
 *                      PORTRAIT
 * LANDSCAPE_LEFT                      LANDSCAPE_RIGHT
 *                      PORTRAIT_UP
 *
 * 摄像头方向：这个最初采用的是iOS的值。iOS本来给出摄像头方向的含义是，当设备方向与摄像头方向相等时，输出的图片的顶部（头部）对应设备的顶部。
 * 即，此时你就能看的一个正确的朝向的图片。但是如果直接在采集时就按设备方向设置摄像头方向，这个代价是摄像头输出的图片就进行了旋转。
 * 这在视频里就会导致机器旋转时，长和宽就会互换，这显然是不好的。因此我们程序默认设置摄像头方向一直为CAMERA_ORIENT_PORTRAIT。
 * 这样输出的长和宽不会因为机器旋转而变化，我们需要处理设备方向的变化。
 *
 * Mirror：iOS默认输出的前置摄像头画面是做了Mirror的，而且iOS没有置这个标志位。导致iOS明明前后摄像头都没有置mirror标志，前后摄像头的旋转方向会不一样。
 * 因此加入了is_iOS标志位，通过视频帧的其他属性确定是否iOS输出。如果不用这个标志位，就得使用另一个现在还成立的假设：前置摄像头没有mirror标志位的是iOS。
 * 注意这个mirror是水平镜像。水平镜像=顺时针旋转180度+垂直镜像。
 *
 * 因此我们可以得出图像的旋转度数关系：
 *                    拍摄端设备方向          拍摄端摄像头方向          接收端设备方向
 *PORTRAIT                 -0                    +0                     +0
 *LANDSCAPE_RIGHT          -90                   +90                    +90
 *PORTRAIT_UP              -180                  +180                   +180
 *LANDSCAPE_LEFT           -270                  +270                   +270
 *
 *通过查表直接把三种方向的旋转结果总和加起来即可。
 *然后处理iOS对镜像的特殊性：
 *			如果是iOS输出的且拍摄端设备方向是LANDSCAPE_LEFT或者LANDSCAPE_RIGHT，则旋转度数再-180
 *最后处理水平镜像。水平镜像不是旋转。所以没有已有的水平镜像或垂直镜像支持的话，只能直接写顶点transform矩阵。
 *
 *
 */
#endif