全球今热点:基于FFMPEG+SDL的简单的视频播放器分析
最近看了雷霄骅前辈的博客《最简单的基于FFMPEG+SDL的视频播放器 ver2 (采用SDL2.0)》,参照他的代码,在windows端实现了一个简单的视频播放器,代码的有部分改动,但是整体的思路和实现的功能是一样的。下面将对实现的源码进行分析,并对其中的一些细节进行记录。
【资料图】
源码分析引入头文件引入头文件。
#include #include extern "C"{#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libswscale/swscale.h"#include "libavutil/imgutils.h"#include "SDL2/SDL.h"}.......
由于ffmpeg和SDL的源码都是C,所以在引入头文件时,可以用extern "C"
用于声明 C 函数,以便使其在 C++ 代码中按照 C 语言的函数命名和调用规则处理。
这部分不是重点,可跳过直接看媒体文件处理的部分
添加了启动参数解析的代码,以便自定义播放的视频。由于是在windows端实现和编译的,所以使用了int WINAPI WinMain
作为程序的入口。
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ ...... return 0;}
因此,想要获取启动参数,需要对数据进行处理。
....... // 获取命令行参数字符串 LPWSTR lpWideCmdLine = GetCommandLineW(); int argc; char *filepath; // 将命令行字符串分割为一个字符串数组,其中每个元素表示一个命令行参数 LPWSTR *argv = CommandLineToArgvW(lpWideCmdLine, &argc); int bufferSize = WideCharToMultiByte(CP_UTF8, 0, argv[1], -1, NULL, 0, NULL, NULL); char *buffer = new char[bufferSize]; // 判断是否指定了播放文件 if (argc > 1) { // 将参数从宽字符转换为多字节字符 WideCharToMultiByte(CP_UTF8, 0, argv[1], -1, buffer, bufferSize, NULL, NULL); filepath = buffer; std::cout << "argv[1]: " << buffer << std::endl; } else { cout << "Please add the path to the video file that requires the part.\n" << endl; return -1; } ......
媒体文件处理读取媒体文件读取媒体文件并获取媒体流的相关信息。代码如下:
....... // av_register_all(); // avformat_network_init(); // 创建一个 AVFormatContext 结构体并进行初始化 pFormatCtx = avformat_alloc_context(); // 打开媒体文件并初始化 AVFormatContext 结构体 if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0) { cout << "Could not open input stream: " << filepath << "\n" << endl; return -1; } // 读取媒体文件并获取媒体流的相关信息 if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { cout << "Could not find stream information.\n" << endl; return -1; } .......
旧版本的ffmpeg程序, 程序开头处, 一般总是av_register_all
,4.x之后,该函数已经废弃,不需要调用了。更多细节可以参考《ffmpeg4.x为什么不再需要调用av_register_all呢》。
在一个完整的媒体文件中,一般会包含视频流和音频流。AVFormatContext
结构体里会存储关于流的各种信息,本例子是对视频流进行处理,所以可以从AVFormatContext
结构体中,获得视频流的下标信息。代码如下:
...... videoindex = -1; // nb_streams 是一个整数类型的字段,表示 AVFormatContext 中包含的流的数量。 for (i = 0; i < pFormatCtx->nb_streams; i++) { // 根据codec_type信息,判断数据流的类型 if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { // 如果 codec_type == AVMEDIA_TYPE_VIDEO,则数据流类型为视频流,记录视频流下标 videoindex = i; break; } } // 如果 videoindex == -1,则说明媒体文件中未找到视频流数据,检查媒体文件 if (videoindex == -1) { cout << "Did not find a video stream.\n" << endl; return -1; } ......
codec_type
代表编码器的类型,常见的类型有
根据视频流信息,查找并打开解码器。代码如下:
...... // 访问视频流的编码参数 pCodecCtx = pFormatCtx->streams[videoindex]->codec; // 根据编码器 ID(codec_id)查找解码器 pCodec = avcodec_find_decoder(pCodecCtx->codec_id); if (pCodec == NULL) { cout << "Could not found.\n" << endl; return -1; } // 打开编解码器 if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { cout << "Could not open codec.\n" << endl; return -1; } ......
图像格式转换...... // 分配 AVFrame 结构体的内存空间 pFrame = av_frame_alloc(); pFrameYUV = av_frame_alloc(); // 分配用于存储图像数据的缓冲区 out_buffer = (unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1)); // 填充pFrameYUV->data,以便后续进行图像处理 av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1); cout << "------------------File Information-----------------\n" << endl; // 输出数据流信息 av_dump_format(pFormatCtx, 0, filepath, 0); cout << "--------------------------------------------------\n" << endl; // 创建图像转换上下文,将原始的像素格式转化为 YUV420P img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); ......
av_image_get_buffer_size
函数,用于计算给定图像参数下所需的缓冲区大小。根据像素格式和图像的宽度和高度,计算出所需的缓冲区大小。此处所用的图像像素格式为YUV420P
。YUV420P 是最常用的像素格式之一,特别在视频编解码领域广泛应用。av_image_fill_arrays
用于向pFrameYUV->data
中填充数据。不过此时原始的图像数据还并未填充进去,只是先分配内存,为后面存储经过格式转换的图像做准备。
创建和配置SDL窗口,renderer,texture和rect。代码如下:
...... // 初始化 SDL 库 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) { cout << "Could not initialize SDL - " << SDL_GetError() << "\n" << endl; return -1; } // 初始化窗口大小为视频大小 screen_w = pCodecCtx->width; screen_h = pCodecCtx->height; // 创建SDL窗口 screen = SDL_CreateWindow("video Player", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_w, screen_h, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); if (!screen) { cout << "SDL: could not creeate window - exiting:\n" << SDL_GetError() << "\n" << endl; return -1; } // 创建renderer sdlRenderer = SDL_CreateRenderer(screen, -1, 0); // 创建texture sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, pCodecCtx->width, pCodecCtx->height); // 初始化rect sdlRect.x = 0; sdlRect.y = 0; sdlRect.w = screen_w; sdlRect.h = screen_h; // 分配一个 AVPacket 结构体的内存空间给packet packet = (AVPacket *)av_malloc(sizeof(AVPacket)); ......
创建一个新的线程,用于检测和处理SDL窗口的活动,代码如下:
int sfp_refresh_thread(void *opaque){ // 初始化线程状态 thread_exit = 0; thread_pause = 0; while (!thread_exit) { if (!thread_pause) { SDL_Event event; // 设置event状态为SFM_REFRESH_EVENT event.type = SFM_REFRESH_EVENT; // 向事件队列中添加事件 SDL_PushEvent(&event); } SDL_Delay(40); } thread_exit = 0; thread_pause = 0; SDL_Event event; // 设置event状态为SFM_BREAK_EVENT event.type = SFM_BREAK_EVENT; SDL_PushEvent(&event); return 0;} int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ ...... // 创建线程,调用sfp_refresh_thread自定义函数 video_tid = SDL_CreateThread(sfp_refresh_thread, NULL, NULL); ...... return 0;}
视频播放获取视频流数据,经过处理和图像转换,将图像填充到SDL窗口,实现视频的播放。代码如下:
...... for (;;) { // 获取窗口活动状态 SDL_WaitEvent(&event); // 播放视频 if (event.type == SFM_REFRESH_EVENT) { while (1) { // 如果没有读取到packet,设置thread_exit为1,结束播放 if (av_read_frame(pFormatCtx, packet) < 0) thread_exit = 1; // 判断packet是否为视频流 if (packet->stream_index == videoindex) break; } // 解码视频帧 ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet); if (ret < 0) { cout << "Decode Error.\n" << endl; return -1; } if (got_picture) { // 将pFrame中的原始图像数据,根据img_convert_ctx转化后,存储到pFrameYUV中,用于在SDL中显示 sws_scale(img_convert_ctx, (const unsigned char *const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize); // 更新texture,更新数据为pFrameYUV->data[0] SDL_UpdateTexture(sdlTexture, NULL, pFrameYUV->data[0], pFrameYUV->linesize[0]); // 清空渲染目标 SDL_RenderClear(sdlRenderer); // 将纹理渲染到sdlRect SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, &sdlRect); // 更新窗口显示 SDL_RenderPresent(sdlRenderer); } // 释放 AVPacket 结构体内存 av_packet_unref(packet); } // 暂停 else if (event.type == SDL_KEYDOWN) { // 如果点击空格键,暂停 if (event.key.keysym.sym == SDLK_SPACE) thread_pause = !thread_pause; } // 窗口退出 else if (event.type == SDL_QUIT) { thread_exit = 1; } // 播放结束 else if (event.type == SFM_BREAK_EVENT) { break; } } ......
内存释放在所有的操作完成后,最后是内存的释放。代码如下:
{ ...... sws_freeContext(img_convert_ctx); SDL_Quit(); av_frame_free(&pFrameYUV); av_frame_free(&pFrame); avcodec_close(pCodecCtx); avformat_close_input(&pFormatCtx); LocalFree(argv); delete[] buffer; return 0;}
完整代码simple_video_player.cpp
#include #include extern "C"{#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libswscale/swscale.h"#include "libavutil/imgutils.h"#include "SDL2/SDL.h"}using namespace std;#define SFM_REFRESH_EVENT (SDL_USEREVENT + 1)#define SFM_BREAK_EVENT (SDL_USEREVENT + 2)int thread_exit = 0;int thread_pause = 0;int sfp_refresh_thread(void *opaque){ thread_exit = 0; thread_pause = 0; while (!thread_exit) { if (!thread_pause) { SDL_Event event; event.type = SFM_REFRESH_EVENT; SDL_PushEvent(&event); } SDL_Delay(40); } thread_exit = 0; thread_pause = 0; SDL_Event event; event.type = SFM_BREAK_EVENT; SDL_PushEvent(&event); return 0;}int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ AVFormatContext *pFormatCtx; int i, videoindex; AVCodecContext *pCodecCtx; AVCodec *pCodec; AVFrame *pFrame, *pFrameYUV; unsigned char *out_buffer; AVPacket *packet; int ret, got_picture; int screen_w, screen_h; SDL_Window *screen; SDL_Renderer *sdlRenderer; SDL_Texture *sdlTexture; SDL_Rect sdlRect; SDL_Thread *video_tid; SDL_Event event; struct SwsContext *img_convert_ctx; LPWSTR lpWideCmdLine = GetCommandLineW(); int argc; char *filepath; LPWSTR *argv = CommandLineToArgvW(lpWideCmdLine, &argc); int bufferSize = WideCharToMultiByte(CP_UTF8, 0, argv[1], -1, NULL, 0, NULL, NULL); char *buffer = new char[bufferSize]; if (argc > 1) { WideCharToMultiByte(CP_UTF8, 0, argv[1], -1, buffer, bufferSize, NULL, NULL); filepath = buffer; std::cout << "argv[1]: " << buffer << std::endl; } else { cout << "Please add the path to the video file that requires the part.\n" << endl; return -1; } // av_register_all(); // avformat_network_init(); pFormatCtx = avformat_alloc_context(); if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0) { cout << "Could not open input stream: " << filepath << "\n" << endl; return -1; } if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { cout << "Could not find stream information.\n" << endl; return -1; } videoindex = -1; for (i = 0; i < pFormatCtx->nb_streams; i++) { if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { videoindex = i; break; } } if (videoindex == -1) { cout << "Did not find a video stream.\n" << endl; return -1; } pCodecCtx = pFormatCtx->streams[videoindex]->codec; pCodec = avcodec_find_decoder(pCodecCtx->codec_id); if (pCodec == NULL) { cout << "Could not found.\n" << endl; return -1; } if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { cout << "Could not open codec.\n" << endl; return -1; } pFrame = av_frame_alloc(); pFrameYUV = av_frame_alloc(); out_buffer = (unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1)); av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1); cout << "------------------File Information-----------------\n" << endl; av_dump_format(pFormatCtx, 0, filepath, 0); cout << "--------------------------------------------------\n" << endl; img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) { cout << "Could not initialize SDL - " << SDL_GetError() << "\n" << endl; return -1; } screen_w = pCodecCtx->width; screen_h = pCodecCtx->height; screen = SDL_CreateWindow("video Player", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_w, screen_h, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); if (!screen) { cout << "SDL: could not creeate window - exiting:\n" << SDL_GetError() << "\n" << endl; return -1; } sdlRenderer = SDL_CreateRenderer(screen, -1, 0); sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, pCodecCtx->width, pCodecCtx->height); sdlRect.x = 0; sdlRect.y = 0; sdlRect.w = screen_w; sdlRect.h = screen_h; packet = (AVPacket *)av_malloc(sizeof(AVPacket)); video_tid = SDL_CreateThread(sfp_refresh_thread, NULL, NULL); for (;;) { SDL_WaitEvent(&event); if (event.type == SFM_REFRESH_EVENT) { while (1) { if (av_read_frame(pFormatCtx, packet) < 0) thread_exit = 1; if (packet->stream_index == videoindex) break; } ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet); if (ret < 0) { cout << "Decode Error.\n" << endl; return -1; } if (got_picture) { sws_scale(img_convert_ctx, (const unsigned char *const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize); SDL_UpdateTexture(sdlTexture, NULL, pFrameYUV->data[0], pFrameYUV->linesize[0]); SDL_RenderClear(sdlRenderer); SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, &sdlRect); SDL_RenderPresent(sdlRenderer); } av_packet_unref(packet); } else if (event.type == SDL_KEYDOWN) { if (event.key.keysym.sym == SDLK_SPACE) thread_pause = !thread_pause; } else if (event.type == SDL_QUIT) { thread_exit = 1; } else if (event.type == SFM_BREAK_EVENT) { break; } } sws_freeContext(img_convert_ctx); SDL_Quit(); av_frame_free(&pFrameYUV); av_frame_free(&pFrame); avcodec_close(pCodecCtx); avformat_close_input(&pFormatCtx); LocalFree(argv); delete[] buffer; return 0;}
标签:
- 全球今热点:基于FFMPEG+SDL的简单的视频播放器分析
- 航天机电(600151.SH):收到合营企业TRP PVE B.V.偿还委托贷款514.12万欧元 全球快讯
- 全球信息:三七互娱:上调回购价是为了更好地开展股权激励等工作丨公司问答
- 【世界报资讯】市领导调研城市更新工作
- 微波炉里能放锡箔纸加热吗_锡箔纸可以放到微波炉里面加热吗
- 15分钟内发生三起爆炸!美国警方悬赏捉拿袭击者-世界聚焦
- 游民金币兑换上新:STEAM充值卡、瑞幸29元饮品券等 天天观焦点
- 肝功能异常多久会肝癌
- 航拍中国感受山河涌动的蓬勃生机
- 少年白头发是什么原因(邓超白头发)
- 6月份我国物流业景气指数为51.7%-天天新动态
- 环球消息!青岛创新“停车场+”建设:在重点地段新增2.4万个车位
- 蜂巢能源IPO进程恢复!
- 视焦点讯!*ST全筑连收4个涨停板
- 仅3天时间完成动迁协议 “宁电入湘”工程送电线路衡南段拆迁顺利推进|今亮点
- 当前时讯:早间公告:四维图新与地平线签署战略合作框架协议
- 首个机器人配送服务平台“小力到家”发布:三年20亿营收
- 沪深股通|亿纬锂能7月3日获外资卖出0.07%股份
- 保障主干电网安全稳定运行,贵阳供电局完成500千伏线路带电作业 环球热讯
- 德邦快递如何转人工服务_德邦快递如何
- 与梅西重聚?罗马诺:迈阿密国际接触拉莫斯,将与两沙特球队竞争
- 造梦西游3朱雀怎么得视频_造梦西游3朱雀怎么得
- 便捷TWS也能支持1200Kbp超无损音质 iQOO TW1明日发布
- 全球速看:金诚信:子公司签订1.17亿美元项目合同
- 热讯:宏英智能:目前在工业机器人及智能机器人领域均有布局
- 2023年南宁西乡塘随迁子女小学报名材料
- 我国七大江河流域将全面进入主汛期_环球微资讯
- 昨天涨停今天跌停是洗盘还是出货_股票昨天涨停今天跌停 天天快资讯
- 头条焦点:突发!日本东京市中心一栋大楼起火,已致至少4人受伤
- 天天即时:隔夜菜吃了真的会中毒吗?隔夜菜究竟能不能吃?真相它来咯!
- 太平人寿衢州中心支公司营业场所变更获批 速看料
- 你有一笔钱到账,请注意查收!-世界简讯
- 信息:基金调研丨淳厚基金调研山大地纬
- 花心歌词花心完整歌词
- 南通师范高等专科学校艺术类专业有哪些?
- 天龙挖宝图攻略(天龙挖宝)-全球快讯
- 每日观点:dota2国服命令(dota2命令)
- 每日速递:无障碍电子地图发布:可规划无障碍路线
- 老北京西红柿打卤面的做法_西红柿打卤面的做法
- ChatGPT访问量或现负增长,市场担忧“人工智能泡沫” 焦点快报
- 爱情谜语大全及答案 爱情谜语大全及答案解析
- 7月3日国内BDO部分装置存检修计划
- 热门看点:车主自己训练常用路线 五菱『记忆行车』解析
- 41股主力资金净流出超1亿元,科大讯飞、浪潮信息、华西股份净流出超5亿元 最资讯
- 【世界快播报】下半年“开门红”!“造车新势力”股价走高,热门板块突然跳水
- 环球信息:郝军亮被任命为陕西环保产业集团董事长!
- 海纳星空科技(08297)7月3日起停牌 以待发布年度业绩-天天报道
- 【短视频】白银:开展特色课程 丰富校园文化
- 【时快讯】诚方创世纪广场与西锦城买哪个合算?海南海口哪些楼盘值得买?
- 报道:广东汕湛高速一辆大巴侧翻 无人员死亡或重伤
-
跨栏美女吴艳妮出圈,又一个超级网红即将诞生,感谢这个时代
全国田径锦标赛,女子100米栏冠军,吴艳妮霸屏了,原来冠军可以这样帅
-
全球观察:赫哲族第11届乌日贡大会在黑龙江抚远启幕
来自北京、哈尔滨、佳木斯、双鸭山等地的15支代表队队员参加了本次民
-
应急照明灯价格是多少钱_应急照明灯价格_全球要闻
1、普通双头消防应急照明灯在网上商城价处于30-60元,高级大型应急灯在
-
从露营徒步到围炉冰茶 “氛围感经济”解锁消费新场景|世界最新
【从露营徒步到围炉冰茶“氛围感经济”解锁消费新场景】近年来,大众消
-
天天观察:苏子油煎鸡蛋的功效_苏子油
1、直接饮用:将苏子油倒在勺子上直接食用,每次只需一小勺,一日三餐空
-
亲情骨折价重返快船 卡椒组合别辜负威少 请带他拿个总冠军吧
亲情骨折价重返快船卡椒组合别辜负威少请带他拿个总冠军吧,威少,湖人,
-
夏季赛单杀榜knght仅第六?小虎牙膏并列第二,第一竟然是他|世界观热点
8分钟Tarzan猴子来下路越塔,LNG成功打出一换二,omg下路对线结束。之
-
城市公园管理出新规 除安全需要外禁设“游人止步”等牌示
日前,为规范我市公园配套建筑及设施规划、建设、使用管理,进一步提升
-
天天滚动:全警出击 重拳整治!榆林公安机关扎实开展夏夜治安巡查宣防集中统一行动
6月30日晚,按照省公安厅、市公安局统一部署,全市公安机关扎实开展夏
-
【天天时快讯】不要抛弃我陈小春_离不开你陈小春
hello大家好,我是大学网网小航来为大家解答以上问题,不要抛弃我陈小
-
YouTube“挥刀”砍向广告拦截器:使用后仅能播放三个视频
YouTube“挥刀”砍向广告拦截器:使用后仅能播放三个视频
-
老城村_关于老城村介绍 环球今头条
1、老城村位于县境东部,东接会盟镇下古村,西连会盟镇陆村。2、南与邙
-
世界焦点!数实融合赋能实体经济 助力传统企业降本增效
数实融合赋能实体经济助力传统企业降本增效---随着新一轮科技革命和产
-
【美】一幢1800年建造的农舍的装修实践 天天视讯
在肯塔基州列克星敦附近有一个占地350英亩的农场,人们很难想象这是
-
【天天快播报】如果无线网络适配器没有显示连接怎么办
在日常生活中,当我们使用数字设备时,我们会遇到各种各样的问题,其中
-
为什么贷款买车比全款买车便宜很多?10年销售揭秘“4S店套路”!_速讯
先亮明身份,本人从事过近10年的一线汽车销售工作,也做过销售经理
-
女孩边充电边玩手机被电流击穿 双脚碳化截肢
日前,沈阳一名女孩小杨(化名)通过“支付宝”的“爱享租”小程序购买
-
暑期档票房或重回百亿时代 影投和院线双料龙头万达电影却股价低迷|世界焦点
暑期档的前战已经打赢。猫眼专业版显示,今年端午档总票房达9 11亿元,
-
环球动态:《边学边修小家电》合集。
,可点击图片放大看。《边学边修小家电》~1。《边学边修小家电》~2
-
首次!王室道歉
据荷兰国家公共广播电视台(NOS)当地时间7月1日报道,荷兰国王威廉-亚
-
又闷又湿!武汉接下来阵雨时时有,气温节节高
又闷又湿!武汉接下来阵雨时时有,气温节节高武汉市三天预报今天白天:
-
北京中轴线文化成为网络视听创作新焦点 世界独家
【文艺观潮】作者:邓秀军(北京外国语大学国际新闻与传播学院教授、博
-
文件加密忘记密码怎么解除手机(文件加密忘记密码怎么解除)
来为大家解答以下的问题,件加密忘记密码怎么解除手机,文件加密忘记密
-
快手电商产业扩张
6月26日,快手电商招商百城行系列活动亮相昆明,活动由快手电商商家发
-
经典群名称_经典群名
1、可以根据姓氏来起群名字2、由于群里的人都姓周,所以微信群名叫:一
-
焦点关注:小米平板5发布时间确认(小米平板5发布)
日前,曾有网友在Redmi产品总监@王腾Thomas微博评论中表示期待5月发布
-
酸辣粉店选址怎么做?兴食客酸辣粉加盟怎么选址?_每日速读
现在市场上非常火的项目有很多,其中酸辣粉是非常有特色的,这个品牌投
-
天天快看:关于金毛犬的电影有哪些_关于金毛的电视剧有哪些
hello大家好,我是大学网网小航来为大家解答以上问题,关于金毛犬的电
-
望风披靡(关于望风披靡介绍)
1、望风披靡,汉语成语,拼音是wàngfēngpīmǐ,比喻军队毫无斗志,
-
多特蒙德vs切尔西 多特关键时刻掉链子 基本情况讲解
1、多特蒙德vs切尔西2、多特关键时刻掉链子3、以上就是关于【多特蒙德v
-
今日看点:《逆水寒手游》天动星回探索攻略
逆水寒手游天动星回探索怎么过?有不少玩家还没有顺利的通关,带来了详
-
消失的她真实事件改编 网友离谱式剧透消失的她 基本情况讲解
大家好,今日关于【消失的她真实事件改编网友离谱式剧透消失的她】迅速
-
同心合力续新篇!龙华区法律援助两项目守护“少年的你”-看热讯
读创 深圳商报首席记者张玮玮通讯员李珊珊文 图6月28日下午,深圳市龙
-
河北弘业地毯集团有限公司
1、河北弘业地毯集团有限公司于2000年05月12日在迁安市工商行政管理局
-
巴媒:阿兰收到来自中国的报价,本轮未随弗鲁米嫩塞出征客场 天天即时看
巴媒:阿兰收到来自中国的报价,本轮未随弗鲁米嫩塞出征客场,中超,中国
-
长治地区邮编_山西省长治市邮编|环球短讯
1、八一路:046000北城街:046000北关街:046000长安路:046000大北街:04
-
官斗:兽心仕途 微速讯
1、在小支行工作已经三年的农村大学生刘波,为工作升迁的事奔波劳累,
-
报告:6月楼市成交未迎止跌行情 7月或将维持弱复苏主基调
6月30日,克而瑞地产研究中心发布了“2023上半年中国房地产企业销售TOP
-
如何做粉条好吃简单的做法?
包菜炒粉条?制作方法:第一步:准备食材。圆白菜半个、红薯粉适量、红
-
今日播报!货币的升值率公式_货币升值率相关内容简介介绍
货币升值率,是指由于货币的发行量少于流通中实际所需要的货币量,从而
-
抖音连麦听不到对方声音怎么回事_为什么我和别人连麦时 我听不到对方的声音-环球最资讯
1、排除对方麦克风原因一、有可能你的话筒线没有插好。2、二、这种可能
-
在word里纸张版面想有横有竖版的怎么弄出来_在word里纸张版面想有横有竖版的怎么弄|天天热议
1、可以通过word中的页面布局功能来进行设置。2、具体操作步骤如下:在
-
意甲:阿德利和图雷都将离开米兰,价格700万欧元
据《米兰体育报》报道,亚辛·阿德利和弗德·巴洛-图雷将结束他们在红
-
独家深度影像丨在地下600米查“密闭” 他们筑牢矿山安全防线 世界热门
原标题:独家深度影像丨在地下600米查“密闭”他们筑牢矿山安全防线编
-
「观云」中小云厂商夹缝求生,七牛云重启上市
本报(chinatimes net cn)记者卢晓见习记者石飞月北京报道去年9月放弃
-
5000万欧卖给巴黎是赚是亏?卢卡斯近5年各项赛事出勤率仅41%_全球速看料
直播吧6月30日讯多方消息确认,合同仅剩1年的拜仁中卫卢卡斯将以约5000
-
当前快讯:青海:现有吸毒人员连续6年下降 复吸率连续5年下降
青海:现有吸毒人员连续6年下降复吸率连续5年下降---资料图为青海省司
-
世界微资讯!水机型灭火器_水机
1、水机专业全称是热能与动力工程专业(水利水电动力工程方向),其主
-
礼赞新时代 争当好少年丨盛梓萌:推动时代新齿轮,铸造华夏新篇章 全球新资讯
推动时代新齿轮,铸造华夏新篇章作者 盛梓萌学校 长沙市天心区青园井岗
-
天天播报:何小鹏:小鹏XNGP率先落地 领先国内友商12-36个月
“XNGP(高阶智能辅助驾驶系统)不是期货,G6交付后用户即可使用。目前
X 关闭
X 关闭