Camera Module

Android Camera Module

CAMERA_MODULE_API_VERSION_2_4

  • Torch mode. Framework 可以打开 flash 而不需要开启 camera device。Camera device 访问 falsh unit 的优先级高于 camera module, 打开 camera device 将会关闭 troch。如果有 资源冲突,例如调用 open() 打开 camera device,camera HAL module 必须通知 framework torch mode 的 status 改变了。
  • External camera(hot-plug camera). API updates 规定,只有在 camera 已经 连接 并且 ready 时 camera static info 才是可用的。
  • Camera arbitration hints.(冲裁提示) 该版本的 module 增加 显式地指示 可以同时打开和使用的 camera devices 的个数。要指定有效的 devices 组合,resource_cost 和 conflicting_devices 字段应该被设置,并且通过 get_camera_info 调用返回。
  • Module initialization method. 该函数被 camera service 在 HAL module 被加载后调用,允许 HAL 完成 one-time 的初始化工作。在其他 module methods 之前被调用。

camera_info

typedef struct camera_info {
    
    int facing;
    int orientation;
    uint32_t device_version;
    const camera_metadata_t *static_camera_characteristics;
    int resource_cost;
    char** conflicting_devices;
    size_t conflicting_devices_length;
} camera_info_t;

facing

  • CAMERA_MODULE_API_VERSION_2_3 之下: CAMERA_FACING_FRONT, CAMERA_FACING_BACK
  • CAMERA_MODULE_API_VERSION_2_4 之上:CAMERA_FACING_FRONT, CAMERA_FACING_BACK, CAMERA_FACING_EXTERNAL

orientation

Image 显示时需要顺时针旋转的角度。可能是 0, 90, 180, 270.

  • CAMERA_MODULE_API_VERSION_2_3 之下:所有的 Camera Module有效
  • CAMERA_MODULE_API_VERSION_2_4 之上:CAMERA_FACING_EXTERNAL无效,其他 有效

device_version

The value of camera_device_t.common.version.

  • CAMERA_MODULE_API_VERSION_1_0: 该字段无效
  • CAMERA_MODULE_API_VERSION_2_0: 有效

static_camera_characteristics

The camera's fixed characteristics.

  • system/media/camera/socs/docs.html 指定的 static camera metadata.
  • 这应该是 一个排序的 metadata buffer,可能被调用者 修改或释放.
  • 该指针应该在 camera module 的生命周期内保持有效, 其中的值可能在 get_camera_info() 之后不会改变.
  • CAMERA_MODULE_API_VERSION_1_0: 无效。
  • CAMERA_MODULE_API_VERSION_2_0: 有效。

resource_cost

使用 camera 的总资源“成本”,表示为 [0-100] 的整数,100 表示Camera subsystem 的限制瓶颈共享资源的总使用。这可能时一个非常粗略的估计,用来提示 camera service 决定禁止多个应用同时打开不同的 cameras.

camera service必须能够同时打开和使用的 camera devices 的 总的资源成本 <=100. 为了确定成本,每个 camera device 必须假设以最大资源消耗 framerate 和stream size被配置操作,通过 camera metadata 暴露。

camera service 可能试图同时打开的 camera device 的总资源消耗 > 100. 这可能成功或失败. 如果成功,由于 资源限制 该配置组合是不被支持,haveing multiple open devices should fail during the configure calls. 如果总资源消耗 <= 100, 不应该失败。

该字段用来决定是否允许 应用 后台使用 camera device 当其他应用在使用 camera device 时。注意:禁止多个应用同时打开同一个 camera devices.

    例如:
     Camera Device 0 = Back Camera
     Camera Device 1 = Front Camera

     同时使用两个设备可能由于 ISP 带宽限制导致帧率降低。

     Configuration:

     Camera Device 0 - resource_cost = 51
                       conflicting_devices = null
     Camera Device 1 - resource_cost = 51
                       conflicting_devices = null

    Result:
        由于 resource const > 100,如果一个更高优先级的应用打开了一个 camera device,那么低优先级的应用无法打开另一个 camera device. 如果低优先级的应用正在使用高优先级应用试图打开的 camera device,那么低优先级的应用将会被强制 disconnecte.

        如果 最高优先级的应用试图打开两个设备,但是可能打开或配置失败。

 * Ex. 2: Camera Device 0 = Left Back Camera
 *        Camera Device 1 = Right Back Camera
 *        Camera Device 2 = Combined stereo camera using both right and left
 *                          back camera sensors used by devices 0, and 1
 *        Camera Device 3 = Front Camera
 *   - Due to do hardware constraints, up to two cameras may be open at once. The
 *     combined stereo camera may never be used at the same time as either of the
 *     two back camera devices (device 0, 1), and typically requires too much
 *     bandwidth to use at the same time as the front camera (device 3).
 *
 *   Configuration:
 *
 *   Camera Device 0 - resource_cost = 50
 *                     conflicting_devices = { 2 }
 *   Camera Device 1 - resource_cost = 50
 *                     conflicting_devices = { 2 }
 *   Camera Device 2 - resource_cost = 100
 *                     conflicting_devices = { 0, 1 }
 *   Camera Device 3 - resource_cost = 50
 *                     conflicting_devices = null
 *
 *   Result:
 *
 *   Based on the conflicting_devices fields, the camera service guarantees that
 *   the following sets of open devices will never be allowed: { 1, 2 }, { 0, 2 }.
 *
 *   Based on the resource_cost fields, if a high-priority foreground application
 *   is using camera device 0, a background application would be allowed to open
 *   camera device 1 or 3 (but would be forced to disconnect it again if the
 *   foreground application opened another device).
 *
 *   The highest priority application may still attempt to simultaneously open
 *   devices 0, 2, and 3, but the HAL may fail in open or configure calls for
 *   this combination.
    * Ex. 3: Camera Device 0 = Back Camera
    *        Camera Device 1 = Front Camera
    *        Camera Device 2 = Low-power Front Camera that uses the same
    *                          sensor as device 1, but only exposes image stream
    *                          resolutions that can be used in low-power mode
    *  - Using both front cameras (device 1, 2) at the same time is impossible due
    *    a shared physical sensor.  Using the back and "high-power" front camera
    *    (device 1) may be impossible for some stream configurations due to hardware
    *    limitations, but the "low-power" front camera option may always be used as
    *    it has special dedicated hardware.
    *
    *   Configuration:
    *
    *   Camera Device 0 - resource_cost = 100
    *                     conflicting_devices = null
    *   Camera Device 1 - resource_cost = 100
    *                     conflicting_devices = { 2 }
    *   Camera Device 2 - resource_cost = 0
    *                     conflicting_devices = { 1 }
    *   Result:
    *
    *   Based on the conflicting_devices fields, the camera service guarantees that
    *   the following sets of open devices will never be allowed: { 1, 2 }.
    *
    *   Based on the resource_cost fields, only the highest priority application
    *   may attempt to open both device 0 and 1 at the same time. If a higher-priority
    *   application is not using device 1 or 2, a low-priority background application
    *   may open device 2 (but will be forced to disconnect it if a higher-priority
    *   application subsequently opens device 1 or 2).
  • CAMERA_MODULE_API_VERSION_2_3 无效
  • CAMERA_MODULE_API_VERSION_2_4 有效

conflicting_devices

不能同时打开的 Camera ID 数组.

  • CAMERA_MODULE_API_VERSION_2_3 无效
  • CAMERA_MODULE_API_VERSION_2_4 有效

conflicting_devices_length

camera_device_status_t

typedef enum camera_device_status {
    CAMERA_DEVICE_STATUS_NOT_PRESENT = 0,
    CAMERA_DEVICE_STATUS_PRESENT = 1,
    CAMERA_DEVICE_STATUS_ENUMERATING = 2,
} camera_device_status_t;

概述

camera_device_status_t 描述 camera devices 的 current status.通过 Camera HAL 调用 camera_module_callbacks.camera_device_status_change() 函数通知.

在 Module 加载后, framework 会假设 camera devices 进入 CAMERA_DEVICE_STATUS_PRESENT 状态. HAL 应该通过 camera_module_callbacks::camera_device_status_change 通知 framework 最初的 NO_PRESENT 的设备.

 * 状态迁移
 *      PRESENT            -> NOT_PRESENT
 *      NOT_PRESENT        -> ENUMERATING
 *      NOT_PRESENT        -> PRESENT
 *      ENUMERATING        -> PRESENT
 *      ENUMERATING        -> NOT_PRESENT

CAMERA_DEVICE_STATUS_NOT_PRESENT

  • camera device 处于 尚未连接 状态. open 会返回失败.
  • CAMERA_MODULE_API_VERSION_2_3 or lower: get_camera_info 正确返回并且如果 camera 已经连接则需提供相同的信息
  • CAMERA_MODULE_API_VERSION_2_4: device 未连接状态通过 get_camera_info 调用 camera device 必须返回 -EINVAL.

CAMERA_DEVICE_STATUS_PRESENT

  • 表示 camera devices 处于 connected , opening 将会成功.
  • CAMERA_MODULE_API_VERSION_2_3 or lower: get_camera_info 返回的 信息不能更改由于该状态改变. 默认 framewok 假设所有的设备处于该状态.
  • CAMERA_MODULE_API_VERSION_2_4: 当 devices status 变为该状态时通过 get_camera_info 返回的信息变为有效.默认,framework会假设所有的设备处于该状态.

CAMERA_DEVICE_STATUS_ENUMERATING

  • 表示 camera devices 处于 connected 状态, 但是正在枚举因此打开设备将返回 -EBUSY.
  • CAMERA_MODULE_API_VERSION_2_3 or lower:camera 处于 PRESENT 状态,调用 get_camera_info 返回成功.
  • CAMERA_MODULE_API_VERSION_2_4: camera devics 处于该状态,get_camera_info 必须返回 -EINVAL, 由于 device 没有 ready.

torch_mode_status_t

typedef enum torch_mode_status {
    TORCH_MODE_STATUS_AVAILABLE_OFF = 1,
    TORCH_MODE_STATUS_AVAILABLE_ON = 2,

} torch_mode_status_t;

概述

描述 troch mode 的当前状态, 由 HAL 通过 camera_module_callbacks.torch_mode_status_change() 提供.

camera device 的 torch mode status 只有在 camera devices 处于 PRESENT 适用. 当 camera device 处于 NOT_PRESENT 状态时, framework 不会调用 set_torch_mode() 来打开 torch mode.

当 module 加载时,framework会假设 torch mode 处于 TORCH_MODE_STATUS_AVAILABLE_OFF 状态, 前提是 camera devices 处于 PRESENT 并且 android.flash.info.available 已经通过 get_camera_info() 上报为 true.

当 camera device 的状态发生变化时,framework 在以下情况下期望的 Camera HAL module 的行为:

  • 之前 disconnected 的 camera device 变为 connected.

    在 camera_module_callbacks::camera_device_status_change() 被调用通知 framework camera devices 是 PRESENT, framework 会假设 camera device's torch mode 处于 TORCH_MODE_STATUS_AVAILABLE_OFF 状态. camera HAL module 不需要调用 camera_module_callbacks::torch_mode_status_change() 除非 flash unit 通过调用 set_torch_mode() 变为了 不可用.

  • 之前 connected 的 camera 变为 disconnected.

    在 camera_module_callbacks::camera_device_status_change() 被调用通知 framework camera device 处于 NOT_PRESENT ,framework 将不会为 处于 disconnected 的 camera device 调用 set_torch_mode() 知道 flash unit 再次变为 available. camera HAL module 不需要调用 camera_module_callbacks::torch_mode_status_change() 来通知 flash unit 变为 不可用.

  • 通过 open() 来打开一个 camera device.

    camera HAL module 必须为所有的 进入到 TORCH_MODE_STATUS_NOT_AVAILABLE 状态的 flash unit 调用 camera_module_callbacks::torch_mode_status_change() 并且不能通过 set_torch_mode() 再次打开.

    在 TORCH_MODE_STATUS_NOT_AVAILABLE 之前 open() 禁止触发 TORCH_MODE_STATUS_AVAILABLE_OFF, 对所有的变为 不可用 的 flash unit.

  • 通过 close() 来关闭一个 camera device.

    camera HAL module 必须为所有的进入到 TORCH_MODE_STATUS_AVAILABLE_OFF 状态的 flash unit 调用 camera_module_callbacks::torch_mode_status_change() 并且可以通过 set_torch_mode() 再次关闭由于再次调用 close() 时已没有足够的资源用来释放.

    注意:
        framework 成功调用 set_torch_mode() 后必须触发 TORCH_MODE_STATUS_AVAILABLE_OFF 或 TORCH_MODE_STATUS_AVAILABLE_ON 的回调.并且必须触发 TORCH_MODE_STATUS_AVAILABLE_OFF 回调为之前已经处于打开的 troch mode, 如果HAL不支持 同时多个 torch modes.

TORCH_MODE_STATUS_NOT_AVAILABLE

  • flash unit 不再是 available 并且 不能通过 set_torch_mode() 打开 torch mode.
  • 如果 troch mode 打开, HAL 将会 在 torch_mode_status_change() 之前关闭.

TORCH_MODE_STATUS_AVAILABLE_OFF

/**
 * A torch mode has become off and available to be turned on via
 * set_torch_mode(). This may happen in the following
 * cases:
 *   1. After the resources to turn on the torch mode have become available.
 *   2. After set_torch_mode() is called to turn off the torch mode.
 *   3. After the framework turned on the torch mode of some other camera
 *      device and HAL had to turn off the torch modes of any camera devices
 *      that were previously on.
 */
TORCH_MODE_STATUS_AVAILABLE_OFF = 1,

TORCH_MODE_STATUS_AVAILABLE_ON

/**
 * A torch mode has become on and available to be turned off via
 * set_torch_mode(). This can happen only after set_torch_mode() is called
 * to turn on the torch mode.
 */

camera_module_callbacks_t

typedef struct camera_module_callbacks {
    void (*camera_device_status_change)(const struct camera_module_callbacks*,
            int camera_id,
            int new_status);
    void (*torch_mode_status_change)(const struct camera_module_callbacks*,
            const char* camera_id,
            int new_status);
} camera_module_callbacks_t;

概述

camera_module_callbacks_t 用来通知 framework camera subsystem 的改变.

  • CAMERA_MODULE_API_VERSION_2_1: camera_device_status_change()
  • CAMERA_MODULE_API_VERSION_2_4: torch_mode_status_change()

camera_device_status_change

  • 回调到 framework 通知 特定 camera device 状态的改变.
  • 在 module load 时,framework 会假设所有的 camera devices 处于 CAMERA_DEVICE_STATUS_PRESENT 状态.
  • HAL 必须调用该方法来通知 framework 任何初始状态为 NO_PRESENT 的 devices.

torch_mode_status_change

  • 回调到 framework 通知和 特定 camera device 相关的 flash unit 的状态的改变.
  • 在 Module load 时,如果 android.flash.info.available 通过 get_camera_info() 被上报为 ture, framework 会假设 torch mode 处于 TORCH_MODE_STATUS_AVAILABLE_OFF.

camera_module_t

typedef struct camera_module {
    hw_module_t common;
    int (*get_number_of_cameras)(void);
    int (*get_camera_info)(int camera_id, struct camera_info *info);
    int (*set_callbacks)(const camera_module_callbacks_t *callbacks);
    void (*get_vendor_tag_ops)(vendor_tag_ops_t* ops);
    int (*open_legacy)(const struct hw_module_t* module, const char* id,
            uint32_t halVersion, struct hw_device_t** device);
    int (*set_torch_mode)(const char* camera_id, bool enabled);
    int (*init)();
    void* reserved[5];
} camera_module_t;

common

  • 所有 moduel 的第一个字段必须是 hw_module_t.

  • common.methods->open 的返回值:

    • 0 : 成功
    • -ENODEV : 由于 internel error, camera device 不能被打开.
    • -EINVAL : 输出参数非法.例如 id 非法,或 module 非法.
    • -EBUSY : camera id 对应的 camera device 已经打开.
    • -EUSERS : 可以通过次方法或者 open_legacy 可以同时打开的 camera devices 个数都打开了.

    所有其他的 返回值 都被认为是 -ENODEV.

get_number_of_cameras

  • CAMERA_MODULE_API_VERSION_2_3 or lower: 返回值必须是静态不变的.
  • CAMERA_MODULE_API_VERSION_2_4 or higher: 返回值必须是静态的,必须计数 built-in cameras,即 CAMERA_FACING_BACK 或 CAMERA_FACING_FRONT, 必须不能包含 external cameras. framework 将使用 camera_device_status_change 回调来管理 external cameras .

get_camera_info

  • static camera information. information 是不变的.
  • 返回值:
    • 0 : 成功
    • -ENODEV: 由于 internal error 导致 information 不能被提供.
    • -EINVAL: 输出参数非法.
  • CAMERA_MODULE_API_VERSION_2_4: 当 camera 处于 disconnected 状态时, camera id 变为非法.调用该方法由于 camera id 是非法将会返回 -EINVAL 并且 camera static metadata 是 NULL.

set_callbacks:

  • 提供以异步通知 framework 的回调函数指针.
  • framework 会在 camera module 加载后 调用该方法, 首先调用 get_number_of_cameras() 方法.
  • CAMERA_MODULE_API_VERSION_1_0, CAMERA_MODULE_API_VERSION_2_0: framework 可能不会调用该函数.
  • CAMERA_MODULE_API_VERSION_2_1: framework 调用合法.
  • 返回值:
    • 0 : 成功.
    • -ENODEV: 由于 internal error 返回失败.
    • -EINVAL: 输入参数非法.

get_vendor_tag_ops

  • Get methods to query for vendor extension metadata tag information.
  • CAMERA_MODULE_API_VERSION_1_x/2_0/2_1: Framework 不会调用该方法.
  • CAMERA_MODULE_API_VERSION_2_2: 有效.

open_legacy

  • 如果 Camera HAL module 支持多个不同版本的 HAL API, open_legacy 打开一个特定 legacy camera HAL device.
  • 例如,如果 camera module 对一个 camera device 同时支持 CAMERA_DEVICE_API_VERSION_1_0 和 CAMERA_DEVICE_API_VERSION_3_2,framework 可以调用该函数打开版本号为 CAMERA_DEVICE_API_VERSION_1_0 的 camera device.
  • 这是一个可选的方法. Camera HAL module 不需要为每个 device 支持超过一个 device HAL version,因此调用该 module 的该方法 可能返回-ENOSYS。对所有的较老版本的 HAL device API 是不支持的,可能返回 -EOPNOTSUPP.
  • CAMERA_MODULE_API_VERSION_1_x/2_0/2_1/2_2: 无效
  • CAMERA_MODULE_API_VERSION_2_3: 有效
  • 返回值:
    • 0 : 成功
    • -ENOSYS : 不支持该方法
    • -EOPNOTSUPP : The requested HAL version is not supported by this method.
    • -EINVAL: 输入参数无效.
    • -EBUSY: camera device 已经打开了.忽略 device HAL version.
    • -EUSERS: 当前可打开的最大 camera devices 个数已经被打开了,通过该方法或者 common.methods->open.

set_torch_mode

概述

打开或关闭和给定camera ID相关的 flash unit 的 torch mode. 如果操作成功,HAL 必须通过 camera_module_callbacks.torch_mode_status_change() 通知 framewok 新的 torch state.

camera device 有访问 flash unit 的最后优先级。当存在资源冲突时,例如 open() camera device,HAL module 必须通过 camera_module_callbacks.torch_mode_status_change() 通知 framewok torch mode 已经关闭并且 torch mode state 已经变为 TORCH_MODE_STATUS_NOT_AVAILABLE。当打开 torch mode 的资源再次可用时,HAL module 必须通过 camera_module_callbacks.torch_mode_status_change() 通知 framewok torch mode state 变为 TORCH_MODE_STATUS_AVAILABLE_OFF.

当 framewok 调用 set_torch_mod() 打开 flash unit 的 torch mode 时,并且 HAL 不能支持同时多个 torch modes,HAL 应该由上一个 set_torch_mode() 关闭 torch mode 并且通知 framewok flash unit 的 torch mode state 变为了 TORCH_MODE_STATUS_AVAILABLE_OFF。

Version information

  • CAMERA_MODULE_API_VERSION_1_x/2_0/2_1/2_2/2_3: 无效
  • CAMERA_MODULE_API_VERSION_2_4: 有效

Return values

  • 0 : 成功
  • -ENOSYS: camera device 不支持该操作. 如果只有 android.flash.info.available 为 false 则返回该值.
  • -EBUSY: The camera device is already in use.
  • -EUSERS: 打开资源不可用的 torch mode, 通常由于其他的 camera device 占用资源使得 flash unit 不可用.
  • -EINVAL: camera_id 非法。

init

概述

在 camera module 加载后,其他方法调用之前由 framewok 调用。如果没有初始化工作,可以设置为 NULL.
可以被实现为完成 one-time 的初始化操作。

version

  • CAMERA_MODULE_API_VERSION_1_x/2_0/2_1/2_2/2_3: 无效
  • CAMERA_MODULE_API_VERSION_2_4: 有效

Return values:

  • 0 : On a successful operation.
  • -ENODEV: 由于 internal error 无法完成初始化.
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容