浦东开发开放二十周年(而立浦东再出发)

浦东大道141号,这座不起眼的二层小楼,曾经是上海总工会所属的东昌区工人俱乐部。1990年4月,这里被确定为上海市人民市政府浦东开发办公室的办公地点。

为了给开发办选择一个体现浦东开发精神的门牌号码,大家展开了热烈讨论。现场一位同志提议:“浦东开发一是一、二是二,一步一个脚印,要实事求是,何不就用‘一是一’的谐音,定为浦东大道141号?”

4月30日,在市政府新闻办公室召开的第一次浦东开发新闻发布会上,第一次公开使用了“浦东大道141号”这一地址。5月3日,浦东开发办在这里正式挂牌成立。

这座楼里做出过无数个对浦东开发开放具有里程碑意义的决策,也记录了无数浦东创业者奉献青春的故事。2010年4月18日,浦东开发开放20周年之际,这里被改造成浦东开发陈列馆,正式向社会开放。

老式电话、红色暖水瓶、凤凰牌自行车、上菱冰箱厂赠送的冰箱等老物件几乎还原了30年前开发办的原貌。浦东开发陈列馆通过实物陈列、场景复原及多媒体回放等多种手段相结合,生动地再现了浦东开发的时代背景和历史进程,展现了浦东这片发展热土始终站在中国改革开放最前沿。

浦东大道141号门牌号 。

工作人员骑的凤凰牌自行车。

浦东开发陈列馆内复原的浦东开发办公室办公区。本文图片由毕梦瀛摄

作者:毕梦瀛

声明:转载此文是出于传递更多信息之目的。若有来源标注错误或侵犯了您的合法权益,请作者持权属证明与本网联系,我们将及时更正、删除,谢谢。

来源: 人民日报客户端上海频道

,

ffmpeg开发入门(开发一个播放器需要用到哪些)

咱们先来看一个流程图:

本篇咱们主要讲解如何利用 FFmpeg API 来对一个输入数据进行解封装,读取原始音频视频信息,然后对音频视频做一些基本操作。基本上在播放器模块中用到的 FFmpeg API 咱们都要对它有一个了解。

FFmpeg 基础知识

解封装

利用 FFmpeg api 来对输入视频进行解封装,先来看一下使用 api 的流程

看完上图是不是对解封装的 API 有一个大概的了解? 从一个 输入 URL 到读取到 压缩数据流 就这么几步,很简单的,下面我们用代码实际演示一下:

1.注册所有函数

av_register_all()

其实在最新的版本中该函数已经过时了,在最低的版本中还是必须调用该函数的。

2.注册网络模块

//初始化网络库(可以打开 rtmp、rtsp、http 等协议的流媒体视频)
avformat_network_init();

3.打开输入流并读取头信息

//参数设置
AVDictionary *opts = NULL;
//设置rtsp流已tcp协议打开
av_dict_set(&opts, "rtsp_transport", "tcp", 0);
//网络延时时间
av_dict_set(&opts, "max_delay", "1000", 0);

//解封装上下文
AVFormatContext *ic = NULL;
int re = avformat_open_input(
&ic,
inpath,
0, // 0表示自动选择解封器
&opts //参数设置,比如rtsp的延时时间
);
//返回值 0 成功
if (re != 0) {
char buf[1024] = {0};
av_strerror(re, buf, sizeof(buf) - 1);
cout << "open " << inpath << " failed! :" << buf << endl;
getchar();
return -1;
}

这里要注意,调用该函数那么在结尾处一定要调用 avformat_close_input()

4.读取媒体文件数据包

//return >=0 if OK, AVERROR_xxx on error
re = avformat_find_stream_info(ic, 0);

//打印视频流详细信息
av_dump_format(ic, 0, inpath, 0);

5.获取音视频流信息

通过遍历的方式获取

//获取音视频流信息 (遍历,函数获取)
for (int i = 0; i < ic->nb_streams; i ) {
AVStream *as = ic->streams[i];
cout << "codec_id = " << as->codecpar->codec_id << endl;
cout << "format = " << as->codecpar->format << endl;

//音频 AVMEDIA_TYPE_AUDIO
if (as->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
audioStream = i;
cout << i << "音频信息" << endl;
cout << "sample_rate = " << as->codecpar->sample_rate << endl;
//AVSampleFormat;
cout << "channels = " << as->codecpar->channels << endl;
//一帧数据?? 单通道样本数
cout << "frame_size = " << as->codecpar->frame_size << endl;
//1024 * 2 * 2 = 4096 fps = sample_rate/frame_size

}
//视频 AVMEDIA_TYPE_VIDEO
else if (as->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStream = i;
cout << i << "视频信息" << endl;
cout << "width=" << as->codecpar->width << endl;
cout << "height=" << as->codecpar->height << endl;
//帧率 fps 分数转换
cout << "video fps = " << r2d(as->avg_frame_rate) << endl;
}
}

2.通过 API 方式获取

//获取视频流
videoStream = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
AVStream *as = ic->streams[videoStream];
cout << i << "视频信息" << endl;
cout << "width=" << as->codecpar->width << endl;
cout << "height=" << as->codecpar->height << endl;
//帧率 fps 分数转换
cout << "video fps = " << r2d(as->avg_frame_rate) << endl;

6.读取压缩数据包

AVPacket *pkt = av_packet_alloc();

for (;;) {
int re = av_read_frame(ic, pkt);
if (re != 0) {
//循环播放
cout << "==============================end==============================" << endl;
break;
}
cout << "pkt->size = " << pkt->size << endl;
//显示的时间
cout << "pkt->pts = " << pkt->pts << endl;

//转换为毫秒,方便做同步
cout << "pkt->pts ms = " << pkt->pts * (r2d(ic->streams[pkt->stream_index]->time_base) * 1000) << endl;

//解码时间
cout << "pkt->dts = " << pkt->dts << endl;
if (pkt->stream_index == videoStream) {
cout << "图像" << endl;
}
if (pkt->stream_index == audioStream) {
cout << "音频" << endl;
}
//释放,引用计数-1 为0释放空间
av_packet_unref(pkt);
}

调试之后的 log

领取音视频开发资料包:音视频流媒体高级开发FFmpegWebRTCRTMPRTSPHLSRTP播放器

企鵝君羊994289133领取资料

解码

调用 ·ffmpeg api 来对音视频压缩数据解码的话,其实也很简单,主要使用如下几个 api ,见下图:

我们接着在解封装的代码基础上进行添加,代码如下:

//找到视频解码器
AVCodec *vcodec = avcodec_find_decoder(ic->streams[videoStream]->codecpar->codec_id);
if (!vcodec) {
cout << "can't find the codec id" << ic->streams[videoStream]->codecpar->codec_id << endl;
getchar();
return -1;
}
//创建视频解码器上下文
AVCodecContext *vctx = avcodec_alloc_context3(vcodec);
//配置解码器上下文参数
avcodec_parameters_to_context(vctx, ic->streams[videoStream]->codecpar);
//配置解码线程
vctx->thread_count = 8;
//打开解码器上下文
re = avcodec_open2(vctx, 0, 0);
if (re != 0) {
char buf[1024] = {0};
av_strerror(re, buf, sizeof(buf) - 1);
cout << "video avcodec_open2 failed!" << buf << endl;
getchar();
return -1;
}
cout << "video avcodec_open2 success!" << endl;

找解码器也可以通过如下 API 形式进行:

AVCodec *avcodec_find_decoder_by_name(const char *name);

如果想要打开音频解码器,代码一样,换下参数即可,下面进行真正解码:

//malloc AVPacket并初始化 AVPacket *pkt = av_packet_alloc(); //接收解码的原始数据 AVFrame *frame = av_frame_alloc(); for (;;) { int re = av_read_frame(ic, pkt); if (re != 0) { break; } //解码视频 //发送 packet 到解码线程 re = avcodec_send_packet(avcc, pkt); //释放,引用计数-1 为0释放空间 av_packet_unref(pkt); //一次 send 可能对于多次 receive for (;;) { re = avcodec_receive_frame(avcc, frame); if (re != 0)break; //释放,引用计数-1 为0释放空间 av_frame_unref(frame); }

这样就可以进行解码了,现在我们添加一些打印参数,比如音频采样信息,视频宽高信息:

总时长:totalMs = 10534 ms视频信息:bitrate=907_500fps = 30.0003codec_id = 86018format = AV_PIX_FMT_YUV420P 11521080 - 1920pict_type= AV_PICTURE_TYPE_I音频信息:sample_rate = 48000channels = 2

视频像素格式转换

视频像素格式其实就是 YUV 转 RGB 的一个过程, FFmpeg 也提供了对应的 API ,它是使用 CPU 运算能力来转换,效率是比较低的。咱们播放器使用 OpenGL GPU 来转,效率比较高。虽然 FFmpeg API 转换效率比较低,但是我们还是可以学习一下的。使用流程如下:

仅仅 2 个 API 就可以达到对 YUV 的转换或者裁剪,代码示例:

const int in_width = frame->width; const int in_height = frame->height; const int out_width = in_width / 2; const int out_height = in_height / 2; /** * @param context : 缩放上下文,如果为 NULL,那么内部会进行创建, * 如果已经存在,参数也没有发生变化,那么就直接返回当前,否者释放缩放上下文,重新创建。 * @param srcW : 输入的宽 * @param srcH : 输入的高 * @param srcFormat : 输入的格式 * @param dstW : 输出的宽 * @param dstH : 输出的高 * @param dstFormat : 输出的格式 * @param flags : 提供了一系列的算法,快速线性,差值,矩阵,不同的算法性能也不同, 快速线性算法性能相对较高。只针对尺寸的变换。 * @param srcFilter : 输入过滤器 * @param dstFilter : 输出过滤器 * @param param : 这个跟 flags 算法相关,一般传入 O * @return : 缩放的上下文 */ vsctx = sws_getCachedContext( vsctx,//传入NULL 会新创建 in_width, in_height, (AVPixelFormat) frame->format, //输入的宽高,格式 out_width, out_height, AV_PIX_FMT_RGBA, //输出的宽高,格式 SWS_BILINEAR, //尺寸变换的算法 0, 0, 0 ); /** * @param c 缩放上下文 * @param srcSlice YUV 切换数据可以是指针,也可以是数组 * @param srcStride 对应 YUV 一行的大小 * @param srcSliceY 这个用不到传入 0 即可 * @param srcSliceH YUV 的高 * @param dst 输出的像素格式数据 * @param dstStride 输出的像素格式数据的大小 * @return 返回转换后的高 */ re = sws_scale(vsctx, frame->data, //输入数据 frame->linesize,//输入行大小 0, frame->height,//输出高度 (uint8_t *const *) (data), //输出数据 lines//输出大小 );

上面的注释都很详细,相信大家也能看的明白,最后我们看下调试后的log,如下:

像素格式尺寸转换上下文创建或者获取成功!in_width=1080in_height=1920out_width=540out_height=960sws_scale success! return height of the output slice =960==============================end==============================

重采样

重采样的意思就是将音频的输入参数统一输出某个特定的值,这样做的好处就是归一化播放器的声音输出。那么怎么使用 FFmpeg API 来进行重采样呢? 先来看一张流程图:

我们还是以之前的代码继续写,

我们统一输出的参数为 sample_rate=48000,sample_channel=2,sample_fml=AV_SAMPLE_FMT_S16

...//音频重采样 SwrContext *asctx = swr_alloc(); //设置重采样参数 asctx = swr_alloc_set_opts(asctx //重采样上下文 , av_get_default_channel_layout(2)//输出声道格式 , AV_SAMPLE_FMT_S16 //输出声音样本格式 , 48000 //输出采样率 , av_get_default_channel_layout(actx->channels)//输入通道数 , actx->sample_fmt //输入声音样本格式 , actx->sample_rate, 0, 0 //输入音频采样率 ); //初始化采样上下文 re = swr_init(asctx); if (re != 0) { char buf[1024] = {0}; av_strerror(re, buf, sizeof(buf) - 1); cout << "audio swr_init failed!" << buf << endl; return -1; } ... //重采样之后存入的数据 unsigned char *pcm = NULL; for (;;) { int re = av_read_frame(ic, pkt); if (re != 0) { //循环播放 cout << "==============================end==============================" << endl;// int ms = 3000; //三秒位置 根据时间基数(分数)转换// long long pos = (double) ms / (double) 1000 * r2d(ic->streams[pkt->stream_index]->time_base);// av_seek_frame(ic, videoStream, pos, AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_FRAME);// continue; break; } cout << "pkt->size = " << pkt->size << endl; //显示的时间 cout << "pkt->pts = " << pkt->pts << endl; //转换为毫秒,方便做同步 cout << "pkt->pts ms = " << pkt->pts * (r2d(ic->streams[pkt->stream_index]->time_base) * 1000) << endl; //解码时间 cout << "pkt->dts = " << pkt->dts << endl; AVCodecContext *avcc = NULL; if (pkt->stream_index == videoStream) { cout << "图像" << endl; avcc = vctx; } if (pkt->stream_index == audioStream) { cout << "音频" << endl; avcc = actx; } //解码视频 //发送 packet 到解码线程 re = avcodec_send_packet(avcc, pkt); //释放,引用计数-1 为0释放空间 av_packet_unref(pkt); if (re != 0) { char buf[1024] = {0}; av_strerror(re, buf, sizeof(buf) - 1); cout << "video avcodec_send_packet failed!" << buf << endl; continue; } //一次 send 可能对于多次 receive for (;;) { re = avcodec_receive_frame(avcc, frame); if (re != 0)break; ... if (avcc == actx) {//音频 uint8_t *data[2] = {0}; if (!pcm) pcm = new uint8_t[frame->nb_samples * 16/8 * 2]; data[0] = {pcm}; int len = swr_convert(asctx, data, frame->nb_samples //输出 , (const uint8_t **) frame->data, frame->nb_samples //输入 ); if (len >= 0) { cout << "swr_convert success return len = " << len << endl; } else { cout << "swr_convert failed return len = " << len << endl; } } }... } if (asctx)swr_close(asctx); if (asctx)swr_free(&asctx);

转换后的log:

swr_convert success return len = 1024

seek 操作

我们如果想要指定某个时间看某段画面的话就需要对视频做 seek 操作,FFmpeg 提供了 av_seek_frame 函数来对视频的跳转,它有 4 个输入参数,含义如下:

/**
* 根据时间戳和音频或视频的索引 seek 到关键帧的操作
*
* @param s 媒体格式上下文
* @param stream_index 流索引,传入 -1 为默认
* @param timestamp 需要跳转到时间戳的位置
* @param flags seek 的模式
* @return >= 0 on success
*/
int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp,
int flags);

我们着重看下最后一个 flags 参数

//AVSEEK_FLAG_BACKWARD

seek 到后面的关键帧

//AVSEEK_FLAG_BYTE

基于以字节为单位的位置查找

//AVSEEK_FLAG_ANY

Seek 到任意一帧,注意不是关键帧,那么会有花屏的可能。

//AVSEEK_FLAG_FRAME

seek 到关键帧的位置

我们一般以这样的形式来进行 seek 操作:

int ms = 3000; //三秒位置 根据时间基数(分数)转换
long long pos = (double) ms / (double) 1000 * r2d(ic->streams[pkt->stream_index]->time_base);
av_seek_frame(ic, videoStream, pos, AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_FRAME);

上面的含义就是定位到 3000 ms 位置后面的关键帧处开始播放。后面播放器 seek 功能的时候我们会介绍如何精准 seek 操作

该篇文章对于 FFmpeg 的知识我们就介绍到这里,后面在开发中如果有新遇见的我会再详细介绍一下。

总结

播放器要用到的 FFmpeg 知识 大概就这么多,可以发现这些 API 其实都比较简单。此刻我相信你已经对这些 API 有一定的印象和了解了吧。

,

猫咬住东西不放还发声

猫发出咕噜咕噜的声音一定是舒服吗,为什么?

小透明突破100个赞了谢谢大家,虽然我觉得是因为一楼开了车,五味杂陈…原回答…

猫咬住东西不放还发声

两个月橘猫总咬人,想了好多办法都改不了,怎么办?

可以训斥它,一旦猫咪做出咬人的举动,就大声呵斥它,把它抱走,让它意识到这样做是错的。但是不建议体罚猫咪,体罚达不到纠正的目的,反而会激起它的逆反情绪。另外,猫咪如果处于长牙期会有磨牙的习惯,可以准备一些玩具给它,比方说球球、猫专用的玩具,小咬铃,小老鼠等等,让小猫能发泄精力,满足它啃咬的本能需要。

撸猫过程中,猫咪突然咬人,随后就舔是后悔了吗?

同意,建议做好两点:
一是平时不要直接拿手去逗猫猫,可以用逗猫棒。如果猫猫求抱抱,才可用手摸它的头部和颈部。二是在猫猫这样做时发声喝止,它一停下马上抽出手,事后花几分钟给它讲道理,做规矩。让它形成一个条件反射的词很重要,比如它想做什么,这件事不能做,你必须有一个常用词制止它,比如不行,不可以之类。它习惯了这个词,每当要调皮,就用这个词发声喝止,亲试有效。现在我家猫猫要做什么它觉得会“越雷池”的事,都会先出声问我,我如果说不可以,它会乖乖放弃。不过习惯需要时间来形成,要有耐心。现在我家猫猫有时也喜欢这样闹着玩,有时还会同时轻轻踢我。但它也会观察我反应,如果我发声制止它或减小力度,或慢慢停下来。其实小的时候从路边抱回来时,我家猫猫特别没有安全感,有点脾气,一般人无法靠近,把它寄养宠物店一周,所有人无法靠近,一靠近就叫咬,后来我去接它时,把它从笼子里抱出来,宠物店小姐姐连连说只有我能抱它。它还喜欢运动,有时嗖一声一道闪电一样从身边掠过,还发出吼吼的声音。刚抱回来那段时间,动不动晚上都要炸一次毛,记得它第一次炸毛时我惊到了,还受到它的攻击,我到处网上搜,宠物店咨询炸毛怎么办。因为那时没法靠近它剪指甲,三天两头我身上时不时带点小伤,还好它小抓咬力度不是大大。有次抓深了,我当即跑到医院去打防疫针,看到它现在的样子,好了不是太多,它也渐渐信任我,有安全感了。还有一次带它出去晒太阳,它躲到车底下,那时我还不懂猫猫有应激这件事,车开动吓坏它,它躲到另一辆车底下,怎么也不出来。我从下午3点守到6-7点,还请了几个朋友钻到车底下,不见它踪影。那时是冬天,后面的几天又下冷雨,它那么小我担心到处找,发动很多人,第三天保安大叔早上6点多打电话说在监控里看到它,我拿着猫食盆冲出去,它躲在绿化带里,看到我嗷嗷叫,放下猫食,它冲过来吃,一边吃一边叫,看得出瘦了点,毛它还是舔得蛮干净的。带回家后拉的巴巴都是小草叶子。因为找猫几天,也发现周围的地盘被各种成年流浪猫占据,它那么小又有残疾没敢去争地盘,只有饿肚子吃草,还好回来没有肠胃炎。说了这么多话,关键付出耐心真诚,善待猫猫,猫是很有灵性,感情的动物。

怎么改掉猫咪乱咬人的毛病?

小猫爱咬人是个挺常见但也非常让人头痛的问题,想解决这个问题,不如换个角度,站在猫的立场上一起看看这到底是个什么情况。图源:全景网和人类的小婴儿一样从长出第一颗乳牙开始,小猫们对于咬东西的兴趣就开始蓬勃发展,出牙时牙床又痛又痒,随便咬点东西可以暂时缓解一下出牙的不舒服。再大 一点之后,和兄弟姐妹之间互相打闹玩耍,咬也是非常重要的途径,也是非常重要的社交礼仪。在猫咪的社会中,在不断的咬别人和被咬之中学习正确的下嘴力度是必须经历的事。图源:全景网随后的生活中,牙齿也是除了爪子以外重要的武器之一,在感到危险和威胁时,咬也成了自我保护的方式。图源:视觉中国了解了这些以后,细心的铲屎官们应该发现了,小猫咬人无外乎就是这三种情况,出牙期牙床不舒服,把你当做同伴玩耍,感到危机时。出牙期的不适可以给它一个磨牙棒,木天蓼或者猫薄荷玩具都是不错的选择。玩耍时一旦感觉到疼就要马上大喝一声,或者用手捏起脖子后的皮肤让它冷静(模仿猫妈教育小猫)教导它正确的玩耍力度。最后,如果它经常感到紧张和危险,因此一靠近就被咬的话,不妨给彼此一点空间,等它慢慢适应后再接近它。有宠原创,个人观点不代表公司立场,转载请注明出处#

猫发出咕噜咕噜的声音一定是舒服吗,为什么?

我觉得不一定。刚带回家的时候,只要有人站在它面前,立刻就咕噜个没完没了,放佛一个V8发动机。对此我还…

家里的猫很喜欢咬东西咬人怎么办呢?

动物小时候都是有一点野性的,对任务非同类都会有一些敌意,所以猫刚养的时候会喜欢咬东西或者是人。但如果你对它足够好,慢慢就会对你放下戒备心,并不会咬你,就算是咬也只是撒娇似的跟你玩闹,不用太过担心,小猫猫养的时间长了感情就会很深了。

家里的猫很喜欢咬东西咬人怎么办呢?

有很多养猫的人都有一个共同的问题,就是猫咪喜欢乱咬东西,只要猫口够得下的,他都会咬的,你的小手头受过伤吗?还有笔,线等等,有几个简单的小办法,保证以后猫就不会乱咬东西了
我们先要解一下为什么猫咪爱咬东西,养过猫的朋友肯定会有手上腿上常是伤痕吧,大家不要都以为这是由于猫咪贪玩淘气弄得,其实这里面是有缘由的。猫咪成长过程需要学习掌控爪子的灵活性,这就是为什么我们经常看到猫咪扑抓的缘由,简单的来说,扑抓、撕咬这些都是猫咪的天性,我们是无法改动它们的天性,只能训练它们,让它们知道自已在干什么。一、改善猫咪淘气的行为
1.不能用手当猫咪的玩具,很多幼猫在小时分精神十分充分,看到会动的东西就会想去攻击,特别是在活动中的手指和小腿
2.要在适当的时候抱猫,若在它玩的过程中抱它是很容易被它攻击的,要到3岁后性情才会稳定
3.为它制定行为规范,在它抓咬物品和主人的时候要给一定的惩罚,让它明白什么能做什么不能做
二、改善猫咪爱抓咬的行为
1.在猫咪准备下嘴咬人的时要发声呵责,或是轻推它的头,意思是告诉它不能这样做
2.在猫咪咬手时将手指往它的喉咙里略微伸一点,异物感会让它感到不适,几次之后就晓得咬人会让自己不舒服,从此就不会再咬人
3.给猫找个适合玩的东西,当他的玩具,让它自己没事找玩具也会减少猫咬东西的习惯
三、改善猫咪咬东西行为
1.添加特殊气味,在猫咪爱咬的东西上涂上一些带有凉凉辣辣的气息的液体,让猫咪厌恶,例如风油精、清凉油等
2.运用辅助工具,用包装将它喜欢咬的东西完整包裹,避免猫咪咬坏
3.把猫喜欢咬的东西收起来,让猫没办法咬到(后两种是第一种方法无效情况下才用,一般第一种方法就可以了)

猫吃东西时发出呜呜的声音是怎么回事?

这是正常的动物行为,因为是为了怕被别人抢,也就是我们百常说的护食的表现。在猫猫在进食的时候,主人尽量不要去度 打扰他们哦,有可能导致消化不良的。问猫猫经常会发出一些声音表达自己的,在你抚摸它时发出呼噜声,是因为答它很享受你的爱抚;弓起背发出呼呼声,是因为有什么事让它感到生气了;毛都竖起来了,哈哈的声声音,那是他们害怕了或者说内是领地被侵犯了,在恐吓对方(如果有狗狗或其他猫靠近,这是他们最正常的反应)。容

小猫突然发出奇怪的叫声还咬着东西不放,我想把东西拿开,它一直咬着不放是...

它跟那东西在玩,玩玩鸡眼了,就会发出奇怪的声

我家猫咪它老是咬到一个东西不放,扯开还闹,怎么回事啊?发情期?每次都是...

猫是有灵性的动物,很敏感谨慎也很挑剔,而且还会有一点点记仇哦,如果你曾经招惹过它,那你就要花些心思去讨好它了,比如每当你从它身边走过的时候要面带笑容(不要小看这一点,猫猫们是可以看懂滴),最好慢慢地轻轻的摸摸它的背或者拍拍它的头,如果它冲你轻柔地叫,说明她基本对你放松警惕了,以后你就可以跟它更亲近,经常抚摸它,喂它食物,不过切记,猫猫吃东西的时候不要呆在它们旁边,它们会很不自在,猫咪是很会护食滴动物呢。如果你不曾招惹过它它还经常挠你你的话,那有可能是它不喜欢你身上的某些气味或是你的一些动作,这样你就可以试着去观察猫猫们,看看它是否会经常盯着你身上的某个部位看,如果是这样,那就说明它对你的这个部位很在意,或者在你做一些动作的时候它会表现的很急躁很反感,如果发现这些,你也找到了令猫猫讨厌的原因了,那么你就要试着稍稍改变一下自己,只要认真的去做,相信不久你就会讨猫猫的欢心了.

本文Hash:b2cc4e5ff1bacf35a07363856c2b7d8c2ec822d2

声明:此文由 leaf 分享发布,并不意味 赞同其观点。文章内容仅供参考,此文如侵犯到您的合法权益,请联系我们。

Baidu
map