热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——解码篇:(二)用ffmpeg解码音频...

其实这篇的内容和(一)用ffmpeg解码视频基本是一样的,重点还是给ffmpeg指定callback函数,而这个函数是从RT

其实这篇的内容和(一)用ffmpeg解码视频基本是一样的,重点还是给ffmpeg指定callback函数,而这个函数是从RTSP服务端那里获取音频数据的。

这里,解码音频的示例代码量之所以比解码视频的略微复杂,主要是因为ffmpeg解码音频时要比解码视频要复杂一点,具体可以参见ffmpeg解码音频示例以及官网示例代码。

具体内容将不再赘述,源码如下:

1 extern "C"
2 {
3 #include
4 #include
5 #include
6 #include
7 #include
8 }
9
10 #include
11 #include
12
13 #ifdef __MINGW32__
14 #undef main /* Prevents SDL from overriding main() */
15 #endif
16
17 #include
18 #include
19 #include
20 #include
21 #include
22
23
24 // compatibility with newer API
25 #if LIBAVCODEC_VERSION_INT 26 #define av_frame_alloc avcodec_alloc_frame
27 #define av_frame_free avcodec_free_frame
28 #endif
29
30 #define SDL_AUDIO_BUFFER_SIZE 1024
31 #define MAX_AUDIO_FRAME_SIZE 192000
32
33 #include
34 #include "rtspClient.h"
35 #include
36 #include <string>
37
38 using std::cout;
39 using std::endl;
40
41 int rtspClientRequest(RtspClient * Client, string url);
42 int fill_iobuffer(void * opaque, uint8_t * buf, int bufsize);
43
44 typedef struct AudioParams {
45 int freq;
46 int channels;
47 int64_t channel_layout;
48 enum AVSampleFormat fmt;
49 int frame_size;
50 int bytes_per_sec;
51 } AudioParams;
52 int sample_rate, nb_channels;
53 int64_t channel_layout;
54 AudioParams audio_hw_params_tgt;
55 AudioParams audio_hw_params_src;
56
57 int resample(AVFrame * af, uint8_t * audio_buf, int * audio_buf_size);
58
59 struct SwrContext * swr_ctx &#61; NULL;
60
61 int resample(AVFrame * af, uint8_t * audio_buf, int * audio_buf_size)
62 {
63 int data_size &#61; 0;
64 int resampled_data_size &#61; 0;
65 int64_t dec_channel_layout;
66 data_size &#61; av_samples_get_buffer_size(NULL,
67 av_frame_get_channels(af),
68 af->nb_samples,
69 (AVSampleFormat)af->format,
70 1);
71
72 dec_channel_layout &#61;
73 (af->channel_layout && av_frame_get_channels(af) &#61;&#61; av_get_channel_layout_nb_channels(af->channel_layout)) ?
74 af->channel_layout : av_get_default_channel_layout(av_frame_get_channels(af));
75 if( af->format !&#61; audio_hw_params_src.fmt ||
76 af->sample_rate !&#61; audio_hw_params_src.freq ||
77 dec_channel_layout !&#61; audio_hw_params_src.channel_layout ||
78 !swr_ctx) {
79 swr_free(&swr_ctx);
80 swr_ctx &#61; swr_alloc_set_opts(NULL,
81 audio_hw_params_tgt.channel_layout, (AVSampleFormat)audio_hw_params_tgt.fmt, audio_hw_params_tgt.freq,
82 dec_channel_layout, (AVSampleFormat)af->format, af->sample_rate,
83 0, NULL);
84 if (!swr_ctx || swr_init(swr_ctx) <0) {
85 av_log(NULL, AV_LOG_ERROR,
86 "Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n",
87 af->sample_rate, av_get_sample_fmt_name((AVSampleFormat)af->format), av_frame_get_channels(af),
88 audio_hw_params_tgt.freq, av_get_sample_fmt_name(audio_hw_params_tgt.fmt), audio_hw_params_tgt.channels);
89 swr_free(&swr_ctx);
90 return -1;
91 }
92 printf("swr_init\n");
93 audio_hw_params_src.channels &#61; av_frame_get_channels(af);
94 audio_hw_params_src.fmt &#61; (AVSampleFormat)af->format;
95 audio_hw_params_src.freq &#61; af->sample_rate;
96 }
97
98 if (swr_ctx) {
99 const uint8_t **in &#61; (const uint8_t **)af->extended_data;
100 uint8_t **out &#61; &audio_buf;
101 int out_count &#61; (int64_t)af->nb_samples * audio_hw_params_tgt.freq / af->sample_rate &#43; 256;
102 int out_size &#61; av_samples_get_buffer_size(NULL, audio_hw_params_tgt.channels, out_count, audio_hw_params_tgt.fmt, 0);
103 int len2;
104 if (out_size <0) {
105 av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size() failed\n");
106 return -1;
107 }
108 av_fast_malloc(&audio_buf, (unsigned int*)audio_buf_size, out_size);
109 if (!audio_buf)
110 return AVERROR(ENOMEM);
111 len2 &#61; swr_convert(swr_ctx, out, out_count, in, af->nb_samples);
112 if (len2 <0) {
113 av_log(NULL, AV_LOG_ERROR, "swr_convert() failed\n");
114 return -1;
115 }
116 if (len2 &#61;&#61; out_count) {
117 av_log(NULL, AV_LOG_WARNING, "audio buffer is probably too small\n");
118 if (swr_init(swr_ctx) <0)
119 swr_free(&swr_ctx);
120 }
121 resampled_data_size &#61; len2 * audio_hw_params_tgt.channels * av_get_bytes_per_sample(audio_hw_params_tgt.fmt);
122 } else {
123 audio_buf &#61; af->data[0];
124 resampled_data_size &#61; data_size;
125 }
126
127 return resampled_data_size;
128 }
129
130 static void sigterm_handler(int sig)
131 {
132 exit(123);
133 }
134
135 typedef struct PacketQueue {
136 AVPacketList *first_pkt, *last_pkt;
137 int nb_packets;
138 int size;
139 SDL_mutex *mutex;
140 SDL_cond *cond;
141 } PacketQueue;
142
143 PacketQueue audioq;
144
145 int quit &#61; 0;
146
147 void packet_queue_init(PacketQueue *q) {
148 memset(q, 0, sizeof(PacketQueue));
149 q->mutex &#61; SDL_CreateMutex();
150 q->cond &#61; SDL_CreateCond();
151 }
152
153 int packet_queue_put(PacketQueue *q, AVPacket *pkt) {
154
155 AVPacketList *pkt1;
156 if(av_dup_packet(pkt) <0) {
157 return -1;
158 }
159 pkt1 &#61; (AVPacketList *)av_malloc(sizeof(AVPacketList));
160 if (!pkt1)
161 return -1;
162 pkt1->pkt &#61; *pkt;
163 pkt1->next &#61; NULL;
164
165
166 SDL_LockMutex(q->mutex);
167
168 if (!q->last_pkt)
169 q->first_pkt &#61; pkt1;
170 else
171 q->last_pkt->next &#61; pkt1;
172 q->last_pkt &#61; pkt1;
173 q->nb_packets&#43;&#43;;
174 q->size &#43;&#61; pkt1->pkt.size;
175 SDL_CondSignal(q->cond);
176
177 SDL_UnlockMutex(q->mutex);
178 return 0;
179 }
180
181 int packet_queue_put_nullpacket(PacketQueue *q, int stream_index)
182 {
183 AVPacket pkt1, *pkt &#61; &pkt1;
184 av_init_packet(pkt);
185 pkt->data &#61; NULL;
186 pkt->size &#61; 0;
187 pkt->stream_index &#61; stream_index;
188 return packet_queue_put(q, pkt);
189 }
190
191 static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
192 {
193 AVPacketList *pkt1;
194 int ret;
195
196 SDL_LockMutex(q->mutex);
197
198 for(;;) {
199
200 if(quit) {
201 ret &#61; -1;
202 break;
203 }
204
205 pkt1 &#61; q->first_pkt;
206 if (pkt1) {
207 q->first_pkt &#61; pkt1->next;
208 if (!q->first_pkt)
209 q->last_pkt &#61; NULL;
210 q->nb_packets--;
211 q->size -&#61; pkt1->pkt.size;
212 *pkt &#61; pkt1->pkt;
213 av_free(pkt1);
214 ret &#61; 1;
215 break;
216 } else if (!block) {
217 ret &#61; 0;
218 break;
219 } else {
220 SDL_CondWait(q->cond, q->mutex);
221 }
222 }
223 SDL_UnlockMutex(q->mutex);
224 return ret;
225 }
226
227 AVFrame frame;
228 int audio_decode_frame(AVCodecContext *aCodecCtx, uint8_t *audio_buf, int buf_size) {
229
230 static AVPacket pkt;
231 static uint8_t *audio_pkt_data &#61; NULL;
232 static int audio_pkt_size &#61; 0;
233
234 int len1, data_size &#61; 0;
235
236 for(;;) {
237 while(audio_pkt_size > 0) {
238 int got_frame &#61; 0;
239 len1 &#61; avcodec_decode_audio4(aCodecCtx, &frame, &got_frame, &pkt);
240 if(len1 <0) {
241 /* if error, skip frame */
242 audio_pkt_size &#61; 0;
243 break;
244 }
245 audio_pkt_data &#43;&#61; len1;
246 audio_pkt_size -&#61; len1;
247 data_size &#61; 0;
248 if(got_frame) {
249 data_size &#61; resample(&frame, audio_buf, &buf_size);
250 // data_size &#61; av_samples_get_buffer_size(NULL,
251 // aCodecCtx->channels,
252 // frame.nb_samples,
253 // aCodecCtx->sample_fmt,
254 // 1);
255 assert(data_size <&#61; buf_size);
256 // memcpy(audio_buf, frame.data[0], data_size);
257 }
258 if(data_size <&#61; 0) {
259 /* No data yet, get more frames */
260 continue;
261 }
262 // memcpy(audio_buf, frame.data[0], data_size);
263
264 /* We have data, return it and come back for more later */
265 return data_size;
266 }
267 if(pkt.data)
268 av_free_packet(&pkt);
269
270 if(quit) {
271 return -1;
272 }
273
274 if(packet_queue_get(&audioq, &pkt, 1) <0) {
275 return -1;
276 }
277 audio_pkt_data &#61; pkt.data;
278 audio_pkt_size &#61; pkt.size;
279 }
280 }
281
282 void audio_callback(void *userdata, Uint8 *stream, int len) {
283
284 AVCodecContext *aCodecCtx &#61; (AVCodecContext *)userdata;
285 int len1, audio_size;
286
287 static uint8_t audio_buf[(MAX_AUDIO_FRAME_SIZE * 3) / 2];
288 static unsigned int audio_buf_size &#61; 0;
289 static unsigned int audio_buf_index &#61; 0;
290
291 while(len > 0) {
292 if(audio_buf_index >&#61; audio_buf_size) {
293 /* We have already sent all our data; get more */
294 audio_size &#61; audio_decode_frame(aCodecCtx, audio_buf, sizeof(audio_buf));
295 if(audio_size <0) {
296 /* If error, output silence */
297 audio_buf_size &#61; 1024; // arbitrary?
298 memset(audio_buf, 0, audio_buf_size);
299 } else {
300 audio_buf_size &#61; audio_size;
301 }
302 audio_buf_index &#61; 0;
303 }
304 len1 &#61; audio_buf_size - audio_buf_index;
305 if(len1 > len)
306 len1 &#61; len;
307 memcpy(stream, (uint8_t *)audio_buf &#43; audio_buf_index, len1);
308 len -&#61; len1;
309 stream &#43;&#61; len1;
310 audio_buf_index &#43;&#61; len1;
311 }
312 }
313
314 int main(int argc, char *argv[]) {
315
316 AVFormatContext *pFormatCtx &#61; NULL;
317 int i, audioStream;
318 AVPacket packet;
319
320 AVCodecContext *aCodecCtxOrig &#61; NULL;
321 AVCodecContext *aCodecCtx &#61; NULL;
322 AVCodec *aCodec &#61; NULL;
323
324 SDL_Event event;
325 SDL_AudioSpec wanted_spec, spec;
326
327 AVInputFormat *piFmt &#61; NULL;
328 RtspClient Client;
329
330 signal(SIGINT , sigterm_handler); /* Interrupt (ANSI). */
331 signal(SIGTERM, sigterm_handler); /* Termination (ANSI). */
332
333 if(argc !&#61; 2) {
334 cout <<"Usage: " <0] <<" " << endl;
335 cout <<"For example: " << endl;
336 cout <0] <<" rtsp://127.0.0.1/ansersion" << endl;
337 return 1;
338 }
339 rtspClientRequest(&Client, argv[1]);
340 // Register all formats and codecs
341 av_register_all();
342
343 if(SDL_Init(SDL_INIT_AUDIO)) {
344 fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
345 exit(1);
346 }
347
348 // // Open video file
349 // if(avformat_open_input(&pFormatCtx, argv[1], NULL, NULL)!&#61;0)
350 // return -1; // Couldn&#39;t open file
351
352 pFormatCtx &#61; NULL;
353 pFormatCtx &#61; avformat_alloc_context();
354 unsigned char * iobuffer &#61; (unsigned char *)av_malloc(32768);
355 AVIOContext * avio &#61; avio_alloc_context(iobuffer, 32768, 0, &Client, fill_iobuffer, NULL, NULL);
356 pFormatCtx->pb &#61; avio;
357
358 if(!avio) {
359 printf("avio_alloc_context error!!!\n");
360 return -1;
361 }
362
363 if(av_probe_input_buffer(avio, &piFmt, "", NULL, 0, 0) <0) {
364 printf("av_probe_input_buffer error!\n");
365 return -1;
366 } else {
367 printf("probe success\n");
368 printf("format: %s[%s]\n", piFmt->name, piFmt->long_name);
369 }
370
371 int err &#61; avformat_open_input(&pFormatCtx, "nothing", NULL, NULL);
372 if(err) {
373 printf("avformat_open_input error: %d\n", err);
374 return -1;
375 }
376 // Retrieve stream information
377 if(avformat_find_stream_info(pFormatCtx, NULL)<0)
378 return -1; // Couldn&#39;t find stream information
379
380 // Dump information about file onto standard error
381 // av_dump_format(pFormatCtx, 0, argv[1], 0);
382 av_dump_format(pFormatCtx, 0, "", 0);
383
384 // Find the first video stream
385 audioStream&#61;-1;
386 for(i&#61;0; inb_streams; i&#43;&#43;) {
387 if(pFormatCtx->streams[i]->codec->codec_type&#61;&#61;AVMEDIA_TYPE_AUDIO &&
388 audioStream <0) {
389 audioStream&#61;i;
390 }
391 }
392 // if(videoStream&#61;&#61;-1)
393 // return -1; // Didn&#39;t find a video stream
394 if(audioStream&#61;&#61;-1)
395 return -1;
396
397 aCodecCtxOrig&#61;pFormatCtx->streams[audioStream]->codec;
398 aCodec &#61; avcodec_find_decoder(aCodecCtxOrig->codec_id);
399 if(!aCodec) {
400 fprintf(stderr, "Unsupported codec!\n");
401 return -1;
402 }
403
404 // Copy context
405 aCodecCtx &#61; avcodec_alloc_context3(aCodec);
406 if(avcodec_copy_context(aCodecCtx, aCodecCtxOrig) !&#61; 0) {
407 fprintf(stderr, "Couldn&#39;t copy codec context");
408 return -1; // Error copying codec context
409 }
410
411 avcodec_open2(aCodecCtx, aCodec, NULL);
412
413 sample_rate &#61; aCodecCtx->sample_rate;
414 nb_channels &#61; aCodecCtx->channels;
415 channel_layout &#61; aCodecCtx->channel_layout;
416
417 // printf("channel_layout&#61;%" PRId64 "\n", channel_layout);
418 printf("channel_layout&#61;%lld\n", channel_layout);
419 printf("nb_channels&#61;%d\n", nb_channels);
420 printf("freq&#61;%d\n", sample_rate);
421
422 if (!channel_layout || nb_channels !&#61; av_get_channel_layout_nb_channels(channel_layout)) {
423 channel_layout &#61; av_get_default_channel_layout(nb_channels);
424 channel_layout &&#61; ~AV_CH_LAYOUT_STEREO_DOWNMIX;
425 printf("correction\n");
426 }
427
428 // Set audio settings from codec info
429 wanted_spec.freq &#61; sample_rate;
430 wanted_spec.format &#61; AUDIO_S16SYS;
431 wanted_spec.channels &#61; nb_channels;
432 wanted_spec.silence &#61; 0;
433 wanted_spec.samples &#61; SDL_AUDIO_BUFFER_SIZE;
434 wanted_spec.callback &#61; audio_callback;
435 wanted_spec.userdata &#61; aCodecCtx;
436
437 if(SDL_OpenAudio(&wanted_spec, &spec) <0) {
438 fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
439 return -1;
440 }
441 printf("freq: %d\tchannels: %d\n", spec.freq, spec.channels);
442
443 audio_hw_params_tgt.fmt &#61; AV_SAMPLE_FMT_S16;
444 audio_hw_params_tgt.freq &#61; spec.freq;
445 audio_hw_params_tgt.channel_layout &#61; channel_layout;
446 audio_hw_params_tgt.channels &#61; spec.channels;
447 audio_hw_params_tgt.frame_size &#61; av_samples_get_buffer_size(NULL, audio_hw_params_tgt.channels, 1, audio_hw_params_tgt.fmt, 1);
448 audio_hw_params_tgt.bytes_per_sec &#61; av_samples_get_buffer_size(NULL, audio_hw_params_tgt.channels, audio_hw_params_tgt.freq, audio_hw_params_tgt.fmt, 1);
449 if (audio_hw_params_tgt.bytes_per_sec <&#61; 0 || audio_hw_params_tgt.frame_size <&#61; 0) {
450 printf("size error\n");
451 return -1;
452 }
453 audio_hw_params_src &#61; audio_hw_params_tgt;
454
455 // audio_st &#61; pFormatCtx->streams[index]
456 packet_queue_init(&audioq);
457 SDL_PauseAudio(0);
458
459 // Read frames and save first five frames to disk
460 i&#61;0;
461 int ret &#61; 1;
462 // while(av_read_frame(pFormatCtx, &packet)>&#61;0) {
463 while(ret >&#61; 0) {
464 ret &#61; av_read_frame(pFormatCtx, &packet);
465
466 if(ret <0) {
467 /* av_read_frame may get error when RTP data are blocked due to the network busy */
468 if(ret &#61;&#61; AVERROR_EOF || avio_feof(pFormatCtx->pb)) {
469 packet_queue_put_nullpacket(&audioq, audioStream);
470 printf("continue ret&#61;%d\n", ret);
471 ret &#61; 0;
472 continue;
473 }
474 printf("ret&#61;%d\n", ret);
475 break;
476 }
477 printf("av_read_frame\n");
478 if(packet.stream_index&#61;&#61;audioStream) {
479 packet_queue_put(&audioq, &packet);
480 } else {
481 av_free_packet(&packet);
482 }
483 // Free the packet that was allocated by av_read_frame
484 SDL_PollEvent(&event);
485 switch(event.type) {
486 case SDL_QUIT:
487 printf("SDL_QUIT\n");
488 quit &#61; 1;
489 SDL_Quit();
490 exit(0);
491 break;
492 default:
493 printf("SDL_Default\n");
494 break;
495 }
496
497 }
498
499 while(1) SDL_Delay(1000);
500
501 // Close the codecs
502 avcodec_close(aCodecCtxOrig);
503 avcodec_close(aCodecCtx);
504
505 // Close the video file
506 avformat_close_input(&pFormatCtx);
507
508 return 0;
509 }
510
511 int rtspClientRequest(RtspClient * Client, string url)
512 {
513 if(!Client) return -1;
514
515 // cout <<"Start play " <
516 string RtspUri(url);
517 // string RtspUri("rtsp://192.168.81.145/ansersion");
518
519 /* Set up rtsp server resource URI */
520 Client->SetURI(RtspUri);
521
522 /* Send DESCRIBE command to server */
523 Client->DoDESCRIBE();
524
525 /* Parse SDP message after sending DESCRIBE command */
526 Client->ParseSDP();
527
528 /* Send SETUP command to set up all &#39;audio&#39; and &#39;video&#39;
529 * sessions which SDP refers. */
530 Client->DoSETUP();
531
532 /* Send PLAY command to play only &#39;video&#39; sessions.*/
533 Client->DoPLAY("audio");
534
535 return 0;
536 }
537
538 int fill_iobuffer(void * opaque, uint8_t * buf, int bufsize) {
539 size_t size &#61; 0;
540 if(!opaque) return -1;
541 RtspClient * Client &#61; (RtspClient *)opaque;
542 if(!Client->GetMediaData("audio", buf, &size, bufsize)) size &#61; 0;
543 printf("fill_iobuffer size: %u\n", size);
544 return size;
545 }

 

注&#xff1a;

1&#xff0c; 兼容myRtspClient-1.2.1及以上版本&#xff0c;且仅支持接收mp2,mp3音频&#xff1b;

2&#xff0c; 音频解码原理可参见&#xff1a;http://www.cnblogs.com/ansersion/p/5265033.html&#xff1b;

3&#xff0c; 示例源码编译需要SDL和ffmpeg&#xff0c;具体可参见解码视频的附录二&#xff1b;

4&#xff0c; 博主编译环境为 x86_64位ubuntu 16.04&#xff0c;以供参考。

 

myRtspClient-1.2.3

ffmpeg-2.8.5

下载源码以及Makefile

 

编译、配置和运行同上一篇&#xff1a;用ffmpeg解码视频

 

上一篇               回目录            下一篇

转:https://www.cnblogs.com/ansersion/p/5285397.html



推荐阅读
  • 1简介本文结合数字信号处理课程和Matlab程序设计课程的相关知识,给出了基于Matlab的音乐播放器的总体设计方案,介绍了播放器主要模块的功能,设计与实现方法.我们将该设 ... [详细]
  • STM32 IO口模拟串口通讯
    转自:http:ziye334.blog.163.comblogstatic224306191201452833850647前阵子,调项目时需要用到低波 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 微信官方授权及获取OpenId的方法,服务器通过SpringBoot实现
    主要步骤:前端获取到code(wx.login),传入服务器服务器通过参数AppID和AppSecret访问官方接口,获取到OpenId ... [详细]
  • 使用freemaker生成Java代码的步骤及示例代码
    本文介绍了使用freemaker这个jar包生成Java代码的步骤,通过提前编辑好的模板,可以避免写重复代码。首先需要在springboot的pom.xml文件中加入freemaker的依赖包。然后编写模板,定义要生成的Java类的属性和方法。最后编写生成代码的类,通过加载模板文件和数据模型,生成Java代码文件。本文提供了示例代码,并展示了文件目录结构。 ... [详细]
  • 流数据流和IO流的使用及应用
    本文介绍了流数据流和IO流的基本概念和用法,包括输入流、输出流、字节流、字符流、缓冲区等。同时还介绍了异常处理和常用的流类,如FileReader、FileWriter、FileInputStream、FileOutputStream、OutputStreamWriter、InputStreamReader、BufferedReader、BufferedWriter等。此外,还介绍了系统流和标准流的使用。 ... [详细]
  • 本文介绍了使用C++Builder实现获取USB优盘序列号的方法,包括相关的代码和说明。通过该方法,可以获取指定盘符的USB优盘序列号,并将其存放在缓冲中。该方法可以在Windows系统中有效地获取USB优盘序列号,并且适用于C++Builder开发环境。 ... [详细]
  • 阅读spring5源码DefaultSingletonBeanRegistry类遇到问题发现SpringBean中存在大量回调机制和aware接口,于是特意去了解 ... [详细]
  • 该楼层疑似违规已被系统折叠隐藏此楼查看此楼*madebyebhrz*#include#include#include#include#include#include#include ... [详细]
  • 开发笔记:图像识别基于主成分分析算法实现人脸二维码识别
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了图像识别基于主成分分析算法实现人脸二维码识别相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 时域|波形_语音处理基于matlab GUI音频数据处理含Matlab源码 1734期
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了语音处理基于matlabGUI音频数据处理含Matlab源码1734期相关的知识,希望对你有一定的参考价值。 ... [详细]
author-avatar
多少年都不会变
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有