当前位置: 首页 > 编程日记 > 正文

FFmpeg中libswscale库简介及测试代码

libswscale库功能主要包括高度优化的图像缩放、颜色空间和像素格式转换操作。

以下是测试代码(test_ffmpeg_libswscale.cpp):

#include "funset.hpp"
#include <string.h>
#include <iostream>
#include <string>
#include <memory>
#include <fstream>#include <opencv2/opencv.hpp>#ifdef __cplusplus
extern "C" {
#endif#include <libswscale/swscale.h>
#include <libavutil/mem.h>
#include <libavutil/imgutils.h>#ifdef __cplusplus
}
#endifint test_ffmpeg_libswscale_bgr_yuv()
{
#ifdef _MSC_VERconst char* image_name = "E:/GitCode/OpenCV_Test/test_images/lena.png";
#elseconst char* image_name = "test_images/lena.png";
#endifcv::Mat mat = cv::imread(image_name, 1);if (!mat.data || mat.channels() != 3) {fprintf(stdout, "fail to read image: %s\n", image_name);return -1;}int width = mat.cols, height = mat.rows;std::unique_ptr<unsigned char[]> data(new unsigned char[width * height * 3 / 2]);std::unique_ptr<unsigned char[]> data2(new unsigned char[width * height * 3 / 2]);{ // bgr --> yuv420pint align = 1;uint8_t *bgr_data[4], *yuv420p_data[4];int bgr_linesize[4], yuv420p_linesize[4];int bytes1 = av_image_alloc(bgr_data, bgr_linesize, width, height, AV_PIX_FMT_BGR24, align);memcpy(bgr_data[0], mat.data, width*height * 3);int bytes2 = av_image_alloc(yuv420p_data, yuv420p_linesize, width, height, AV_PIX_FMT_YUV420P, align);fprintf(stdout, "bgr size: %d, linesize: %d, %d, %d, yuv420p size: %d, linesize: %d, %d, %d\n",bytes1, bgr_linesize[0], bgr_linesize[1], bgr_linesize[2], bytes2, yuv420p_linesize[0], yuv420p_linesize[1], yuv420p_linesize[2]);if (bytes1 < 0 || bytes2 < 0) {fprintf(stderr, "bgr or yuv420p alloc buffer failed: %d, %d\n", bytes1, bytes2);return -1;}SwsContext* sws_ctx = sws_getContext(width, height, AV_PIX_FMT_BGR24, width, height, AV_PIX_FMT_YUV420P, 0, nullptr, nullptr, nullptr);if (!sws_ctx) {fprintf(stderr, "fail to sws_getContext\n");return -1;}sws_scale(sws_ctx, bgr_data, bgr_linesize, 0, height, yuv420p_data, yuv420p_linesize);#ifdef _MSC_VERconst char* name = "E:/GitCode/OpenCV_Test/test_images/512w_512h.yuv420p";
#elseconst char* name = "test_images/512w_512h.yuv420p";
#endifstd::ofstream fout(name, std::ios::out | std::ios::binary);if (!fout.is_open()) {fprintf(stderr, "fail to open file: %s\n", name);return -1;}memcpy(data.get(), yuv420p_data[0], width*height);memcpy(data.get() + width*height, yuv420p_data[1], width*height / 4);memcpy(data.get() + width*height * 5 / 4, yuv420p_data[2], width*height / 4);fout.write((char*)data.get(), width * height * 3 / 2);fout.close();av_freep(&bgr_data[0]);av_freep(&yuv420p_data[0]);sws_freeContext(sws_ctx);
}{ // yuv420p --> bgr24int align = 1;uint8_t *bgr_data[4], *yuv420p_data[4];int bgr_linesize[4], yuv420p_linesize[4];int bytes1 = av_image_alloc(bgr_data, bgr_linesize, width, height, AV_PIX_FMT_BGR24, align);int bytes2 = av_image_alloc(yuv420p_data, yuv420p_linesize, width, height, AV_PIX_FMT_YUV420P, align);memcpy(yuv420p_data[0], data.get(), width*height);memcpy(yuv420p_data[1], data.get() + width*height, width*height / 4);memcpy(yuv420p_data[2], data.get() + width*height * 5 / 4, width*height / 4);fprintf(stdout, "bgr size: %d, linesize: %d, %d, %d, yuv420p size: %d, linesize: %d, %d, %d\n",bytes1, bgr_linesize[0], bgr_linesize[1], bgr_linesize[2], bytes2, yuv420p_linesize[0], yuv420p_linesize[1], yuv420p_linesize[2]);if (bytes1 < 0 || bytes2 < 0) {fprintf(stderr, "bgr or yuv420p alloc buffer failed: %d, %d\n", bytes1, bytes2);return -1;}SwsContext* sws_ctx = sws_getContext(width, height, AV_PIX_FMT_YUV420P, width, height, AV_PIX_FMT_BGR24, 0, nullptr, nullptr, nullptr);if (!sws_ctx) {fprintf(stderr, "fail to sws_getContext\n");return -1;}sws_scale(sws_ctx, yuv420p_data, yuv420p_linesize, 0, height, bgr_data, bgr_linesize);#ifdef _MSC_VERconst char* name = "E:/GitCode/OpenCV_Test/test_images/yuv420ptobgr24.jpg";
#elseconst char* name = "test_images/yuv420ptobgr24.jpg";
#endifcv::Mat dst(height, width, CV_8UC3, bgr_data[0]);cv::imwrite(name, dst);av_freep(&bgr_data[0]);av_freep(&yuv420p_data[0]);sws_freeContext(sws_ctx);
}{ // bgr --> nv12int align = 1;uint8_t *bgr_data[4], *nv12_data[4];int bgr_linesize[4], nv12_linesize[4];int bytes1 = av_image_alloc(bgr_data, bgr_linesize, width, height, AV_PIX_FMT_BGR24, align);memcpy(bgr_data[0], mat.data, width*height * 3);int bytes2 = av_image_alloc(nv12_data, nv12_linesize, width, height, AV_PIX_FMT_NV12, align);fprintf(stdout, "bgr size: %d, linesize: %d, %d, %d, nv12 size: %d, linesize: %d, %d, %d\n",bytes1, bgr_linesize[0], bgr_linesize[1], bgr_linesize[2], bytes2, nv12_linesize[0], nv12_linesize[1], nv12_linesize[2]);if (bytes1 < 0 || bytes2 < 0) {fprintf(stderr, "bgr or nv12 alloc buffer failed: %d, %d\n", bytes1, bytes2);return -1;}SwsContext* sws_ctx = sws_getContext(width, height, AV_PIX_FMT_BGR24, width, height, AV_PIX_FMT_NV12, 0, nullptr, nullptr, nullptr);if (!sws_ctx) {fprintf(stderr, "fail to sws_getContext\n");return -1;}sws_scale(sws_ctx, bgr_data, bgr_linesize, 0, height, nv12_data, nv12_linesize);#ifdef _MSC_VERconst char* name = "E:/GitCode/OpenCV_Test/test_images/512w_512h.nv12";
#elseconst char* name = "test_images/512w_512h.nv12";
#endifstd::ofstream fout(name, std::ios::out | std::ios::binary);if (!fout.is_open()) {fprintf(stderr, "fail to open file: %s\n", name);return -1;}memcpy(data2.get(), nv12_data[0], width*height);memcpy(data2.get() + width*height, nv12_data[1], width*height / 2);fout.write((char*)data2.get(), width * height * 3 / 2);fout.close();av_freep(&bgr_data[0]);av_freep(&nv12_data[0]);sws_freeContext(sws_ctx);
}{ // nv12 --> bgr24int align = 1;uint8_t *bgr_data[4], *nv12_data[4];int bgr_linesize[4], nv12_linesize[4];int bytes1 = av_image_alloc(bgr_data, bgr_linesize, width, height, AV_PIX_FMT_BGR24, align);int bytes2 = av_image_alloc(nv12_data, nv12_linesize, width, height, AV_PIX_FMT_NV12, align);memcpy(nv12_data[0], data2.get(), width*height);memcpy(nv12_data[1], data2.get() + width*height, width*height / 2);fprintf(stdout, "bgr size: %d, linesize: %d, %d, %d, nv12 size: %d, linesize: %d, %d, %d\n",bytes1, bgr_linesize[0], bgr_linesize[1], bgr_linesize[2], bytes2, nv12_linesize[0], nv12_linesize[1], nv12_linesize[2]);if (bytes1 < 0 || bytes2 < 0) {fprintf(stderr, "bgr or nv12 alloc buffer failed: %d, %d\n", bytes1, bytes2);return -1;}SwsContext* sws_ctx = sws_getContext(width, height, AV_PIX_FMT_NV12, width, height, AV_PIX_FMT_BGR24, 0, nullptr, nullptr, nullptr);if (!sws_ctx) {fprintf(stderr, "fail to sws_getContext\n");return -1;}sws_scale(sws_ctx, nv12_data, nv12_linesize, 0, height, bgr_data, bgr_linesize);#ifdef _MSC_VERconst char* name = "E:/GitCode/OpenCV_Test/test_images/nv12tobgr24.jpg";
#elseconst char* name = "test_images/nv12tobgr24.jpg";
#endifcv::Mat dst(height, width, CV_8UC3, bgr_data[0]);cv::imwrite(name, dst);av_freep(&bgr_data[0]);av_freep(&nv12_data[0]);sws_freeContext(sws_ctx);
}return 0;
}int test_ffmpeg_libswscale_scale()
{// bgr to rgb and resize
#ifdef _MSC_VERconst char* image_name = "E:/GitCode/OpenCV_Test/test_images/lena.png";
#elseconst char* image_name = "test_images/lena.png";	
#endifcv::Mat src = cv::imread(image_name, 1); if (!src.data || src.channels() != 3) {fprintf(stderr, "fail to read image: %s\n", image_name);return -1;}int width_src = src.cols, height_src = src.rows;int width_dst = width_src / 1.5, height_dst = height_src / 1.2;std::unique_ptr<uint8_t[]> data(new uint8_t[width_dst * height_dst * 3]);SwsContext* ctx = sws_getContext(width_src, height_src, AV_PIX_FMT_BGR24, width_dst, height_dst, AV_PIX_FMT_RGB24, SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);if (!ctx) {fprintf(stderr, "fail to sws_getContext\n");return -1;}const uint8_t* p1[1] = {(const uint8_t*)src.data};uint8_t* p2[1] = {data.get()};int src_stride[1] = {width_src * 3};int dst_stride[1] = {width_dst * 3};sws_scale(ctx, p1, src_stride, 0, height_src, p2, dst_stride);
#ifdef _MSC_VERconst char* result_image_name = "E:/GitCode/OpenCV_Test/test_images/lena_resize_rgb_libswscale.png";
#elseconst char* result_image_name = "test_images/lena_resize_rgb_libswscale.png";
#endifcv::Mat dst(height_dst, width_dst, CV_8UC3, (unsigned char*)data.get());cv::imwrite(result_image_name, dst);sws_freeContext(ctx);return 0;
}int test_ffmpeg_libswscale_colorspace()
{fprintf(stdout, "swscale configuration: %s\n", swscale_configuration());fprintf(stdout, "swscale license: %s\n", swscale_license());AVPixelFormat pix_fmt = AV_PIX_FMT_YUV420P;fprintf(stdout, "is supported input:: %d\n", sws_isSupportedInput(pix_fmt));pix_fmt = AV_PIX_FMT_BGR24;fprintf(stdout, "is supported output: %d\n", sws_isSupportedOutput(pix_fmt));pix_fmt = AV_PIX_FMT_GRAY8;fprintf(stdout, "is supported endianness conversion: %d\n", sws_isSupportedEndiannessConversion(pix_fmt));// bgr to gray
#ifdef _MSC_VERconst char* image_name = "E:/GitCode/OpenCV_Test/test_images/lena.png";
#elseconst char* image_name = "test_images/lena.png";	
#endifcv::Mat src = cv::imread(image_name, 1); if (!src.data || src.channels() != 3) {fprintf(stderr, "fail to read image: %s\n", image_name);return -1;}int width = src.cols, height = src.rows;std::unique_ptr<uint8_t[]> data(new uint8_t[width * height]);SwsContext* ctx = sws_getContext(width, height, AV_PIX_FMT_BGR24, width, height, AV_PIX_FMT_GRAY8, 0, nullptr, nullptr, nullptr);if (!ctx) {fprintf(stderr, "fail to sws_getContext\n");return -1;}const uint8_t* p1[1] = {(const uint8_t*)src.data};uint8_t* p2[1] = {data.get()};int src_stride[1] = {width*3};int dst_stride[1] = {width};sws_scale(ctx, p1, src_stride, 0, height, p2, dst_stride);
#ifdef _MSC_VERconst char* result_image_name = "E:/GitCode/OpenCV_Test/test_images/lena_gray_libswscale.png";
#elseconst char* result_image_name = "test_images/lena_gray_libswscale.png";
#endifcv::Mat dst(height, width, CV_8UC1, (unsigned char*)data.get());cv::imwrite(result_image_name, dst);sws_freeContext(ctx);return 0;
}

其中test_ffmpeg_libswscale_scale的执行结果如下:

GitHub:https://github.com/fengbingchun/OpenCV_Test

相关文章:

FFmpeg中libswresample库简介及测试代码

libswresample库功能主要包括高度优化的音频重采样、rematrixing和样本格式转换操作。 以下是测试代码(test_ffmpeg_libswresample.cpp)&#xff0c;对音频了解较少&#xff0c;测试代码是参考examples中的&#xff1a; #include "funset.hpp" #include <iostre…

高德地图POI搜索,附近地图搜索,类似附近的人搜索

效果图&#xff1a; 首先导入道德地图的SDK&#xff0c;导入步骤不在这里介绍 2&#xff1a;包含头文件&#xff1a; [objc] view plaincopy #import <AMapSearchKit/AMapSearchAPI.h> 3&#xff1a;代码 [javascript] view plaincopy property(nonatomic,strong)AMap…

手把手教你实现PySpark机器学习项目——回归算法

作者 | hecongqing 来源 | AI算法之心&#xff08;ID:AIHeartForYou&#xff09;【导读】PySpark作为工业界常用于处理大数据以及分布式计算的工具&#xff0c;特别是在算法建模时起到了非常大的作用。PySpark如何建模呢&#xff1f;这篇文章手把手带你入门PySpark&#xff0c;…

mcDropdown使用方法

最近使用了mcDropdown插件&#xff0c;百度一查&#xff0c;资料较少&#xff0c;只看到了mcDropdown官网的英文说明文档&#xff0c;所以今天就写点&#xff0c;以便以后使用。 第一步&#xff1a;引用jquery库和css jQuery v1.2.6 (or higher)*jquery.mcdropdown.js Plug-inj…

Windows上通过VLC播放器搭建rtsp流媒体测试地址操作步骤

1. 从https://www.videolan.org/index.zh.html 下载最新的windows 64bit 3.0.6版本并安装&#xff1b; 2. 打开VLC media player&#xff0c;依次点击按钮&#xff1a;”媒体” --> “流”&#xff0c;如下图所示&#xff1a; 3. 点击”添加”按钮&#xff0c;选择一个视频…

Swift - AppDelegate.swift类中默认方法的介绍

项目创建后&#xff0c;AppDelegate类中默认带有如下几个方法&#xff0c;具体功能如下&#xff1a; 1&#xff0c;应用程序第一次运行时执行这个方法只有在App第一次运行的时候被执行过一次&#xff0c;每次App从后台激活时都不会再执行该方法。&#xff08;注&#xff1a;所有…

上热搜了!“学了Python6个月,竟然找不到工作!”

在编程界&#xff0c;Python是一种神奇的存在。有人认为&#xff0c;只有用Python才能优雅写代码&#xff0c;提高代码效率&#xff1b;但另一部分人恨不能把Python喷成筛子。那么&#xff0c;Python到底有没有用&#xff0c;为什么用Python找不到工作&#xff1f;CSDN小姐姐带…

Linux0.00内核为什么要自己设置0x80号陷阱门来调用write_char过程?

我一开始没注意这个问题&#xff0c;只是通过陷阱门觉得很绕弯子&#xff0c;为何不在3级用户代码里直接调用write_char&#xff0c;今天自己写程序想用call调用代码段&#xff0c;才发现了大问题。我写了个类似于write_char的过程&#xff0c;代码如下&#xff1a;dividing_li…

iOS支付宝(Alipay)接入详细流程,比微信支付更简单,项目实战中的问题分析

最近在项目中接入了微信支付和支付宝支付&#xff0c;总的来说没有那么坑&#xff0c;很多人都说文档不全什么的&#xff0c;确实没有面面 俱到&#xff0c;但是认真一步一步测试下还是妥妥的&#xff0c;再配合懂得后台&#xff0c;效率也是很高的&#xff0c;看了这篇文章&a…

LIVE555简介及在Windows上通过VS2013编译操作步骤

LIVE555是使用开放标准协议(RTP/RTCP, RTSP, SIP)形成的一组用于多媒体流C库。这些库支持的平台包括Unix(包括Linux和Mac OS X)、Windows和QNX(以及其它符号POSIX的系统)。这些库已经被用于实现的应用例如LIVE555媒体服务器、LIVE555代理服务器(RTSP服务器应用)以及vobStreamer…

GitHub App终于来了,iPhone用户可尝鲜,「同性交友」更加便捷

整理 | 夕颜出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;【导读】据外媒 VentureBeat 报道&#xff0c;在 11 月 13 日举行的 GitHub Universe 上&#xff0c;微软宣布了面向程序员和开发人员的一系列升级&#xff0c;包括针对 iOS 智能手机和 iPad 推出的 GitHub…

[NHibernate]代码生成器的使用

目录 写在前面 文档与系列文章 代码生成器的使用 总结 写在前面 前面的文章介绍了nhibernate的相关知识&#xff0c;都是自己手敲的代码&#xff0c;有时候显得特别的麻烦&#xff0c;比如你必须编写持久化类&#xff0c;映射文件等等&#xff0c;举得例子比较简单&#xff0c;…

RapidJSON简介及使用

RapidJSON是腾讯开源的一个高效的C JSON解析器及生成器&#xff0c;它是只有头文件的C库。RapidJSON是跨平台的&#xff0c;支持Windows, Linux, Mac OS X及iOS, Android。它的源码在https://github.com/Tencent/rapidjson/&#xff0c;稳定版本为2016年发布的1.1.0版本。 Rap…

高德地图关键字搜索oc版

.h文件 // MapSearchViewController.h // JMT // // Created by walker on 16/10/11. // Copyright © 2016年 BOOTCAMP. All rights reserved. // #import <UIKit/UIKit.h> #import <AMapNaviKit/MaMapKit.h> #import <AMapSearchKit/AMapSearchKit.h&…

同一个内容,对比Java、C、PHP、Python的代码量,结局意外了

为什么都说Python容易上手&#xff01;是真的吗&#xff1f;都说Python通俗易懂&#xff0c;容易上手&#xff0c;甚至不少网友表示「完成同一个任务&#xff0c;C 语言要写 1000 行代码&#xff0c;Java 只需要写 100 行&#xff0c;而 Python 可能只要 20 行」到底是真的还是…

图片存储思考:

http://blog.csdn.net/liuruhong/article/details/4072386

LIVE555中RTSP客户端接收媒体流分析及测试代码

LIVE555中testProgs目录下的testRTSPClient.cpp代码用于测试接收RTSP URL指定的媒体流&#xff0c;向服务器端发送的命令包括&#xff1a;DESCRIBE、SETUP、PLAY、TERADOWN。 1. 设置使用环境&#xff1a;new一个BasicTaskScheduler对象&#xff1b;new一个BasicUsageEnvironm…

swift代理传值

比如我们这个场景&#xff0c;B要给A传值&#xff0c;那B就拥有代理属性&#xff0c; A就是B的代理&#xff0c;很简单吧&#xff01;有代理那就离不开协议&#xff0c;所以第一步就是声明协议。在那里声明了&#xff1f;谁拥有代理属性就在那里声明&#xff0c;所以代码就是这…

重磅:腾讯正式开源图计算框架Plato,十亿级节点图计算进入分钟级时代

整理 | 唐小引 来源 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;腾讯开源进化 8 年&#xff0c;进入爆发期。 继刚刚连续开源 TubeMQ、Tencent Kona JDK、TBase、TKEStack 四款重点开源项目后&#xff0c;腾讯开源再次迎来重磅项目&#xff01;北京时间 11 月 14 日…

类似ngnix的多进程监听用例

2019独角兽企业重金招聘Python工程师标准>>> 多进程监听适合于短连接&#xff0c;且连接间无交集的应用。前两天简单写了一个&#xff0c;在这里保存一下。 #include <sys/types.h>#include <stdarg.h>#include <signal.h>#include <unistd.h&…

今日头条李磊等最新论文:用于文本生成的核化贝叶斯Softmax

译者 | Raku 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;摘要用于文本生成的神经模型需要在解码阶段具有适当词嵌入的softmax层&#xff0c;大多数现有方法采用每个单词单点嵌入的方式&#xff0c;但是一个单词可能具有多种意义&#xff0c;在不同的背景下&#…

FFmpeg中RTSP客户端拉流测试代码

之前在https://blog.csdn.net/fengbingchun/article/details/91355410中给出了通过LIVE555实现拉流的测试代码&#xff0c;这里通过FFmpeg来实现&#xff0c;代码量远小于LIVE555&#xff0c;实现模块在libavformat。 在4.0及以上版本中&#xff0c;FFmpeg有了些变动&#xff…

虚拟机下运行linux通过nat模式与主机通信、与外网连接

首先&#xff1a;打开虚拟机的编辑菜单下的虚拟网络编辑器&#xff0c;选中VMnet8 NAT模式。通过NAT设置获取网关IP&#xff0c;通过DHCP获取可配置的IP区间。同时&#xff0c;将虚拟机的虚拟机菜单的设置选项中的网络适配器改为NAT模式。即可&#xff01; 打开linux&#xff0…

远程过程调用RPC简介

RPC(Remote Procedure Call, 远程过程调用)&#xff1a;是一种通过网络从远程计算机程序上请求服务&#xff0c;而不需要了解底层网络技术的思想。 RPC是一种技术思想而非一种规范或协议&#xff0c;常见RPC技术和框架有&#xff1a; (1). 应用级的服务框架&#xff1a;阿里的…

iOS开发:沙盒机制以及利用沙盒存储字符串、数组、字典等数据

iOS开发&#xff1a;沙盒机制以及利用沙盒存储字符串、数组、字典等数据 1、初识沙盒&#xff1a;(1)、存储在内存中的数据&#xff0c;程序关闭&#xff0c;内存释放&#xff0c;数据就会丢失&#xff0c;这种数据是临时的。要想数据永久保存&#xff0c;将数据保存成文件&am…

支撑亿级用户“刷手机”​,百度Feed流背后的新技术装备有多牛?

导读&#xff1a;截止到2018年底&#xff0c;我国网民使用手机上网的比例已高达98.6%&#xff0c;移动互联网基本全方位覆盖。智能手机的操作模式让我们更倾向于通过简单的“划屏”动作&#xff0c;相对于传统的文本交互方式来获取信息&#xff0c;用户更希望一拿起手机就能刷到…

玩转高性能超猛防火墙nf-HiPAC

中华国学&#xff0c;用英文讲的&#xff0c;稀里糊涂听了个大概&#xff0c;不得不佩服西方人的缜密的逻辑思维&#xff0c;竟然把玄之又玄的道家思想说的跟牛顿定律一般&#xff0c;佩服。归家&#xff0c;又收到了邮件&#xff0c;还是关于nf-hipac的&#xff0c;不知不觉就…

ios 沙盒 plist 数据的读取和存储

plist 只能存储基本的数据类型 和 array 字典 [objc] view plaincopy - (void)saveArray { // 1.获得沙盒根路径 NSString *home NSHomeDirectory(); // 2.document路径 NSString *docPath [home stringByAppendingPathComponent:"Document…

FFmpeg实现获取USB摄像头视频流测试代码

通过USB摄像头(注&#xff1a;windows7/10下使用内置摄像头&#xff0c;linux下接普通的usb摄像头(Logitech))获取视频流用到的模块包括avformat和avdevice。头文件仅include avdevice.h即可&#xff0c;因为avdevice.h中会include avformat.h。libavdevice库是libavformat的一…

重磅!明略发布数据中台战略和三大解决方案

11月15日&#xff0c;明略科技在上海举办以“FASTER 聚变增长新动力”为主题的2019数据智能峰会&#xff0c;宣布“打造智能时代的企业中台”新战略&#xff0c;同时推出了两大新产品“新一代数据中台”和“营销智能平台”&#xff0c;以及三大行业解决方案&#xff0c;分别是“…