ffmpeg提取音頻播放器總結

ffmpeg提取音頻播放器總結;?
一:簡介?
從編寫音頻播放器代碼到完成播放器編寫,測試,整整5天的時間,這時間還不算之前對 ffmpeg熟悉的時間,可以說是歷經千辛萬苦,終于搞出來了,雖然最終效果還不是很理想,但是已經可以很流暢的播放某些歌曲了,說是某些歌曲,是因為還有些歌曲播放效果不是很好,有些許雜音,至于那些歌曲能夠順利播放,那些不能夠,我現在也摸不準是什么原因導致的,有待進一步鉆研,等啥時候調好了,就用自己的這個播放器聽歌曲了,嘿嘿;?
a:插播:)?
/**************/?
這一部分屬于插播內容,就不用看了;?
tv視頻播放;?
采用img_convert時,是轉換成24RGB快呢,還是32RGB快呢?可能前者快吧;似乎用qimage的話只能轉換成32RGB了;因為它只有三種顏色深度1-p, 8-p, 32-p所以,只能選擇32-p了;?

下面是AVFrame的結構,具體可以看這里:?
http://cekirdek.pardus.org.tr/~ismail/ffmpeg-docs/avcodec_8h-source.html#l00424?
就是一個宏定義,咳。。。?
/**************/?
二:音頻播放器原理?
音頻播放器過程如下所示:?
打開文件--分析文件格式--打開對應解碼器--讀取一音頻幀--解碼音頻幀--音頻數據寫入音頻設備--循環讀取音頻幀--再解碼。。。如此循環下去;?
整個播放器實現原理詳細說明為,采用ffmpeg提供的API函數先用av_open_input_file打開音頻文件,分析文件得到格式信息,然后識別格式,并查找對應的解碼器,再得到針對此音頻文件的解碼器之后,用av_read_frame從音頻文件中讀取一幀,然后對其用 avcodec_decode_audio函數進行解碼,在將解碼之后的PCM音頻數據直接寫到audio設備(/dev/dsp)上,根據linux音頻設備的原理,此時你就應該聽到悅耳的歌聲了;?
三:重點要點說明?
在這個過程當中有幾處需要特別注意,下面詳細說明一下:?
1、不同音頻文件格式對音頻壓縮率不同,導致對于同一個音頻包,你解壓出來的音頻數據大小也是不一樣的,這一點無需驚奇,但是對于這些解壓出來的音頻數據,一定要保證全部寫到聲卡當中去,這樣才能夠作為你能聽到悅耳歌聲的基礎,這里留意一下,這只是一個基礎,要想完全實現好此播放器,下一點更是不可或缺的;我之前之所以在調試時總是聽到聲音很雜亂,或者帶有金屬聲,就是因為聲音沒有全部寫到音頻設備中去,當然,可能或多或少也有一些寫音頻數據的太快的原故;?
2、在確認了解碼后的數據是完整的之后,可以將數據寫入到音頻設備當中了(/dev/dsp),這里很關鍵的一點就是要對音頻設備進行設置,否則你也聽不到你想聽到的聲音:(?
對音頻設備的設置主要是四個方面,這不代表其他方面不設置哦:?
設置采樣率(有關音頻采樣率,在我blog前面的文章當中有說明,一般有44100hz,48000hz,22050?不記得了,你查看我blog中前面的文章吧,嘿嘿):?
ioctl (fd, SNDCTL_DSP_SPEED, &(pCodecCtx->sample_rate));?
設置音頻聲道數(這個很好理解,一般都是立體聲了)?
// set channels;?
? ? i = pCodecCtx->channels;?
? ? #ifdef AUDIO_DEBUG?
? ? printf ("pCodecCtx->channels:%d\n", pCodecCtx->channels);?
? ? #endif?
? ? if ((ioctl (fd, SNDCTL_DSP_CHANNELS, &i)) == -1)?
? ? {?
? ?? ???fprintf (stderr, "Set Audio Channels %d failed:%s\n", i,?
? ?? ?? ?? ? strerror (errno));?
? ?? ???return (-1);?
? ? }?
這里需要說明的一點是,如果是立體聲,則此處i應該等于2,而不是1,網上很多文章這里都說明的不正確,我之前就一直以為立體聲為1,單聲道為0,總是不出聲音,后來一狠心,改為2,盡然ok,faint;?
結論:網上的東西啊,不可全信之。。。。。。。。。。。。。。。。。。。。。。。。。。。?
設置量化位數(這個量化位數是指對聲音的振幅進行采樣的位數,以前一般是8位,現在以16位居多,更高位數對于普通用戶用不著,只能在專業音樂中才有價值)?
i = AFMT_S16_LE;? ?? ???(16位,小端存儲,也即intel的倒序數據存儲)?
ioctl (fd, SNDCTL_DSP_SETFMT, &i);?
設置音頻驅動級緩存?
i = (0x0004 << 16) + 0x000b;? ?? ???// four 2kb buffer;你看著對應改就行了(這里是四個2kb緩存)?
ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &i);?
這里也可以不設置,用系統默認自定義也可;?

另外有一個疑問也順帶解決了:?
Q:播放音頻和pts有關系么?需要他來調整播放的快慢么?就像視頻那樣??
A:基本沒有關系,至少我目前沒有用到這個咚咚,pts應該實在視頻當中采用到的,pts是顯示時間戳,dts是解碼時間戳;以后搞到視頻再詳細說明啦;不需要,對于寫音頻數據,系統,或者更準確的說驅動會自動調整,寫得快,他會阻塞你的寫,寫的慢?你的機器該換了,嘿嘿,玩笑一個。。。增加緩存可以解決慢的問題;?
Q:如何調試音頻播放器??
這里需要注意兩點,一點是你要保證解碼后的數據確實是PCM數據;第二點是你要確定數據準確無誤,全部寫入音頻文件,否則會出現各種各樣的暴音啊之類的事情,不可預測;?
有關這兩點你可以分別調試;第一點,可以將解碼后的數據寫入一個文件當中,然后利用一些音頻分析軟件(能夠分析PCM數據),播放即可,看你解碼的數據是否正確,完整,如果沒有問題,那這一步就完成了,我在這里沒有卡殼,直接過;下一步,我是扔進去很多時間,由于我的指針使用不當,導致總是漏寫數據,我在下面也會把我的錯誤代碼貼出來,以做對比,大家也都可以來看看,這一點我想經常和指針打交道的就肯定沒問題了的;?

這里向大家推薦windows下的cooledit軟件,不用找注冊碼,反正能試用,沒問題,功能絕對夠用,而且分析聲音頻播非常形象,鄭重推薦;雖然windows和linux切換麻煩了點,嘿嘿:)不過如果你有兩臺電腦,另說啦。。。?
下面將這個音頻播放器的源代碼貼出來,以便大家互相學習;?
我的編譯環境是?
os:Neoshine linux (2.6.14-1.1644_dt_5);?
硬件:普通pc機;?
/***************************************************************************?
*? ?? ?? ?? ?main.cc?
*?
*??Thu Nov??9 20:47:33 2006?
*??Copyright??2006?
*??Email lsosa.BIT?
*??Author lsosa.BIT?
****************************************************************************/?

#include <avcodec.h>?
#include <avformat.h>?
#include <avutil.h>?
#include <assert.h>?
#include <stdio.h>?
#include <stdlib.h>?
#include <X11/Xlib.h>?
#include <sys/soundcard.h>?
#include <sys/stat.h>?
#include <fcntl.h>?
#include <sys/ioctl.h>?
#include <unistd.h>?
#include <errno.h>?
#include <string.h>?
#include <sched.h>?

#define ALL_DEBUG?

#ifdef ALL_DEBUG?
? ? #define AV_DEBUG?
? ? #define AUDIO_DEBUG?
#endif?

//------------------------------------------------------------------------------?
// manipulations for file?
int open_file (char *file_name, int mode)?
{?
? ? // open file file_name and return the file descriptor;?
? ? int fd;?

? ? if ((fd = open (file_name, mode)) < 0)?
? ? {?
? ?? ???fprintf (stderr, " Can't open %s!\n", file_name);?
? ?? ???exit (-1);?
? ? }?
? ? return fd;?
}?

int set_audio (int fd, AVCodecContext * pCodecCtx)?
{?
? ? // set the properties of audio device with pCodecCtx;?

? ? int i, err;?
? ? /* 設置適當的參數,使得聲音設備工作正常 */?
? ? /* 詳細情況請參考Linux關于聲卡編程的文檔 */?
? ?
? ? i = 0;?
? ? ioctl (fd, SNDCTL_DSP_RESET, &i);?
? ? i = 0;?
? ? ioctl (fd, SNDCTL_DSP_SYNC, &i);?
? ? i = 1;?
? ? ioctl (fd, SNDCTL_DSP_NONBLOCK, &i);?
? ?
? ? // set sample rate;?
? ? #ifdef AUDIO_DEBUG?
? ? printf ("pCodecCtx->sample_rate:%d\n", pCodecCtx->sample_rate);?
? ? #endif?
? ? i = pCodecCtx->sample_rate;?
? ? if (ioctl (fd, SNDCTL_DSP_SPEED, &i) == -1)?
? ? {?
? ?? ???fprintf (stderr, "Set speed to %d failed:%s\n", i,?
? ?? ?? ?? ? strerror (errno));?
? ?? ???return (-1);?
? ? }?
? ? if (i != pCodecCtx->sample_rate)?
? ? {?
? ?? ???fprintf (stderr, "do not support speed %d,supported is %d\n",?
? ?? ?? ?? ? pCodecCtx->sample_rate, i);?
? ?? ???return (-1);?
? ? }?
? ?
? ? // set channels;?
? ? i = pCodecCtx->channels;?
? ? #ifdef AUDIO_DEBUG?
? ? printf ("pCodecCtx->channels:%d\n", pCodecCtx->channels);?
? ? #endif?
? ? if ((ioctl (fd, SNDCTL_DSP_CHANNELS, &i)) == -1)?
? ? {?
? ?? ???fprintf (stderr, "Set Audio Channels %d failed:%s\n", i,?
? ?? ?? ?? ? strerror (errno));?
? ?? ???return (-1);?
? ? }?
? ? if (i != pCodecCtx->channels)?
? ? {?
? ?? ???fprintf (stderr, "do not support channel %d,supported %d\n",?
? ?? ?? ?? ?pCodecCtx->channels, i);?
? ?? ???return (-1);?
? ? }?
? ? // set bit format;?
? ? i = AFMT_S16_LE;?
? ? if (ioctl (fd, SNDCTL_DSP_SETFMT, &i) == -1)?
? ? {?
? ?? ???fprintf (stderr, "Set fmt to bit %d failed:%s\n", i,?
? ?? ?? ?? ? strerror (errno));?
? ?? ???return (-1);?
? ? }?
? ? if (i != AFMT_S16_LE)?
? ? {?
? ?? ???fprintf (stderr, "do not support bit %d, supported %d\n",?
? ?? ?? ?? ? AFMT_S16_LE, i);?
? ?? ???return (-1);?
? ? }?
? ?
? ? // set application buffer size;?
? ? // i = (0x00032 << 16) + 0x000c;? ?? ???// 32 4kb buffer;?
? ? // ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &i);?
? ? i = 1;?
? ? ioctl (fd, SNDCTL_DSP_PROFILE, &i);?
? ?
? ? return 0;?
}?

void close_file (int fd)?
{?
? ? // close the file pointed by file descriptor fd;?
? ? close (fd);?
}?

//------------------------------------------------------------------------------?
// handle audio;?

void display_AVCodecContext(AVCodecContext *pCodecCtx){?
? ? //?
? ? #define STDOUT stderr?
? ? fprintf(STDOUT, "pCodecCtx->bit_rate:%d\n", pCodecCtx->bit_rate);?
? ? fprintf(STDOUT, "pCodecCtx->sample_rate:%d\n", pCodecCtx->sample_rate);?
? ? fprintf(STDOUT, "pCodecCtx->channels:%d\n", pCodecCtx->channels);?
? ? fprintf(STDOUT, "pCodecCtx->frame_size:%d\n", pCodecCtx->frame_size);?
? ? fprintf(STDOUT, "pCodecCtx->frame_number:%d\n", pCodecCtx->frame_number);?
? ? fprintf(STDOUT, "pCodecCtx->delay:%d\n", pCodecCtx->delay);?
? ? fprintf(STDOUT, "pCodecCtx->frame_bits:%d\n", pCodecCtx->frame_bits);?
}?

// error if return -1;?
// success if return 0;?
// 這里要用到指向指針的指針,否則傳不到值;?
int av_init (char *file_name, AVFormatContext ** pFormatCtx,?
? ???AVCodecContext ** pCodecCtx, int *p_audioStream)?
{?
? ? // init the codec and format of input file file_name;?
? ? int audioStream, i;?
? ? AVCodec *pCodec;?
? ? // catch error?
? ? assert(file_name != NULL);?
? ? assert(*pFormatCtx != NULL);?
? ? assert(*pCodecCtx != NULL);?
? ?
? ? // Register all formats and codecs?
? ? av_register_all ();?
? ?
? ? // open file?
? ? if (av_open_input_file (pFormatCtx, file_name, NULL, 0, NULL) != 0){?
? ?? ???// Couldn't open file?
? ?? ???fprintf (stderr, " Can't open %s!\n", file_name);?
? ?? ???return -1;? ?
? ? }?

? ? // Retrieve stream information?
? ? if (av_find_stream_info (*pFormatCtx) < 0){?
? ?? ???// Couldn't find stream information?
? ?? ???return -1;? ?
? ? }?
? ?
? ? #ifdef AV_DEBUG?
? ? // Dump information about file onto standard error?
? ? dump_format (*pFormatCtx, 0, file_name, false);?
? ? #endif?
? ?
? ? // Find the first audio and video stream respectively?
? ? audioStream = -1;?
? ? for (i = 0; i < (*pFormatCtx)->nb_streams; i++){?
? ?? ???if ((*pFormatCtx)->streams->codec->codec_type ==?
? ?? ?? ?? ?CODEC_TYPE_AUDIO)?
? ?? ???{?
? ?? ?? ?? ?audioStream = i;?
? ?? ???}?
? ? }?
? ?
? ? #ifdef AV_DEBUG?
? ? // dump_stream_info(pFormatCtx);?
? ? #endif?
? ?
? ? // exclude error?
? ? if (audioStream == -1){?
? ?? ???// Didn't find a audio or video stream?
? ?? ???return -1;? ?
? ? }?

? ? // Get a pointer to the codec context for the audio stream?
? ? *pCodecCtx = (*pFormatCtx)->streams[audioStream]->codec;?

? ? // Find the decoder for the audio stream?
? ? pCodec = avcodec_find_decoder ((*pCodecCtx)->codec_id);?
? ? if (pCodec == NULL)?
? ?? ???return -1;? ? // Codec not found?

? ? // Open codec?
? ? if (avcodec_open ((*pCodecCtx), pCodec) < 0){?
? ?? ???return -1;? ? // Could not open codec?
? ? }?
? ?
? ? #ifdef AUDIO_DEBUG?
? ? // printf ("pCodecCtx->sample_rate:%d, audioStream:%d\n", (*pCodecCtx)->sample_rate, audioStream);?
? ? // display_AVCodecContext(*pCodecCtx);?
? ? #endif?
? ?
? ? *p_audioStream = audioStream;?
? ?
? ? return 0;?
}?

void av_play (AVFormatContext * pFormatCtx,?
? ???AVCodecContext * pCodecCtx, int audioStream)?
{?
? ? // which was read from one frame;?
? ? AVPacket packet;?
? ? uint32_t len;?
? ? uint8_t decompressed_audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];?
? ? int decompressed_audio_buf_size;?
? ? uint8_t * p_decompressed_audio_buf;?
? ? int fd = -1;? ? // audio file or test file??
? ? char filename[64] = "/dev/dsp";?
? ? int mode = O_WRONLY;?
? ? //?
? ?
? ? // open audio file or written file?
? ? // printf("fd:%d", fd);?
? ? fd = open_file(filename, mode);?
? ? // printf("fd:%d", fd);?
? ? //?
? ? set_audio(fd, pCodecCtx);?
? ?
? ? //?
? ? printf("(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2=%d\n", (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2);
? ? printf("AVCODEC_MAX_AUDIO_FRAME_SIZE=%d\n", AVCODEC_MAX_AUDIO_FRAME_SIZE);?
? ?
? ? // for a test?
? ? // char test_file[256] = "my_pcm.pcm";?
? ? // fd = open_file(test_file, mode);?
? ?
? ? #ifdef AV_DEBUG?
? ? static int size = 0;?
? ? #endif?
? ? //?
? ?
? ? // set the sched priority?
? ? // 這是為了提高音頻優先級;不曉得起作用沒;?
? ? int policy = SCHED_FIFO;?
? ? sched_setscheduler(0, policy, NULL);?
? ?
? ? int write_buf_size = 4196;?
? ? int written_size;?
? ? while (av_read_frame (pFormatCtx, &packet) >= 0)?
? ? {?
? ?? ???// Is this a packet from the audio stream??
? ?? ???// 判斷是否音頻幀;?
? ?? ???if (packet.stream_index == audioStream)?
? ?? ???{?
? ?? ?? ?? ?// Decode audio frame?
? ?? ?? ?? ?// 解碼音頻數據為pcm數據;?
? ?? ?? ?? ?len = avcodec_decode_audio (pCodecCtx,?
? ?? ?? ?? ?? ?? ?? ?? ?? ? (int16_t *)decompressed_audio_buf,?
? ?? ?? ?? ?? ?? ?? ?? ?? ? &decompressed_audio_buf_size,? ?? ???// it is the decompressed frame in BYTES 解碼后的數據大小,字節為單位;?
? ?? ?? ?? ?? ?? ?? ?? ?? ? packet.data,?
? ?? ?? ?? ?? ?? ?? ?? ?? ? packet.size );?
? ?? ?? ?? ?// printf("len:%d, packet.size:%d\n", len, packet.size);?
? ?? ?? ?? ?if ( len < 0 ){?
? ?? ?? ?? ?? ? // if error len = -1?
? ?? ?? ?? ?? ? printf("+----- error in decoding audio frame\n");?
? ?? ?? ?? ?? ? // exit(0);?
? ?? ?? ?? ?}?
? ?? ?? ?? ?// test lsosa?
? ?? ?? ???
? ?? ?? ???
? ?? ?? ?? ?// printf("size = %d\n", size);?
? ?? ?? ?? ?//******************************************************************?
? ?? ?? ?? ?// 重點是這一部分,使用oss播放的代碼,之前的數據寫是否完整的問題就是出在這里,或者是前面的set_audio函數設置不正確;?
? ?? ?? ?? ?// audio_buf_info info;?
? ?? ?? ?? ?p_decompressed_audio_buf = decompressed_audio_buf;?
? ?? ?? ?? ?while ( decompressed_audio_buf_size > 0 ){?
? ?? ?? ?? ?? ? // 解碼后數據不為零,則播放之,為零,則;?
? ?? ?? ?? ?? ? written_size = write(fd, p_decompressed_audio_buf, decompressed_audio_buf_size);?
? ?? ?? ?? ?? ? if ( written_size == -1 ){?
? ?? ?? ?? ?? ?? ???// printf("error:decompressed_audio_buf_size:%d, decompressed_audio_buf_size:%d, %s\n", \?
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???decompressed_audio_buf_size, decompressed_audio_buf_size,strerror(errno));?
? ?? ?? ?? ?? ?? ???// usleep(100);?
? ?? ?? ?? ?? ?? ???continue;?
? ?? ?? ?? ?? ? }?
? ?? ?? ?? ?? ? // printf("decompressed_audio_buf_size:%d, written_size:%d\n", \?
? ?? ?? ?? ?? ?? ?? ?? ?? ? decompressed_audio_buf_size, written_size);?
? ?? ?? ?? ?? ? decompressed_audio_buf_size -= written_size;?
? ?? ?? ?? ?? ? p_decompressed_audio_buf += written_size;?
? ?? ?? ?? ?? ?
? ?? ?? ?? ?}// end while?
? ?? ?? ?? ?//******************************************************************?
? ?? ???}?
? ?? ???else?
? ?? ???{?
? ?? ?? ?? ?printf("+----- this is not audio frame\n");?
? ?? ???}// end if?
? ?? ???// Free the packet that was allocated by av_read_frame?
? ?? ???av_free_packet (&packet);?
? ? }// end while of reading one frame;?
? ?? ??
? ? close_file(fd);?
}?

void av_close (AVFormatContext * pFormatCtx, AVCodecContext * pCodecCtx)?
{?
? ? // close the file and codec?

? ? // Close the codec?
? ? avcodec_close (pCodecCtx);?

? ? // Close the video file?
? ? av_close_input_file (pFormatCtx);?
}?

//------------------------------------------------------------------------------?

int main (int argc, char **argv){?
? ? //?
? ? AVFormatContext *pFormatCtx;?
? ? int audioStream = -1;?
? ? AVCodecContext *pCodecCtx;?
? ?
? ? // exclude the error about args;?
? ? if ( argc != 2 ){?
? ?? ???printf("please give a file name\n");?
? ?? ???exit(0);?
? ? }?
? ?
? ? // 注意:這里要用到指向指針的指針,是因為這個初始化函數需要對指針的地址進行改動,?
? ? // 所以,只有這么做,才能達到目的;?
? ? if ( av_init(argv[1], &pFormatCtx, &pCodecCtx, &audioStream) < 0 ){?
? ?? ???//?
? ?? ???fprintf(stderr, "error when av_init\n");?
? ? }?
? ?
? ? // play the audio file?
? ? av_play(pFormatCtx, pCodecCtx, audioStream);?
? ?
? ? // close all the opend files?
? ? av_close(pFormatCtx, pCodecCtx);?
? ?
}?


http://weiyuhu.iteye.com/blog/576610


ffmpeg提取音頻播放器總結


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/454986.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/454986.shtml
英文地址,請注明出處:http://en.pswp.cn/news/454986.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【BZOJ 4103】 [Thu Summer Camp 2015]異或運算 可持久化01Trie

我們觀察數據&#xff1a;樹套樹 PASS 主席樹 PASS 一層一個Trie PASS 再看&#xff0c;異或&#xff01;我們就把目光暫時定在01Tire然后我們發現&#xff0c;我們可以帶著一堆點在01Trie上行走&#xff0c;因為O(n*q*30m*30)是一個可選復雜度。 我們想一下我們正常的時候…

Docker學習筆記——Java及Tomcat Dockerfile

1、Java Dockerfile創建項目目錄java&#xff0c;目錄下上傳所需java版本壓縮包&#xff0c;并創建Dockerfile文件&#xff0c;項目結構如下&#xff1a;java-Dockerfile-jdk-8u111-linux-x64.gzDockerfile內容&#xff1a;# JAVA # Version 1.8.0_111 # SOURCE_IMAGE FROM cen…

rabbitmq接口異常函數方法_RabbitMQ監控(三):監控隊列狀態

#RabbitMQ 監控(三)驗證RabbitMQ健康運行只是確保消息通信架構可靠性的一部分&#xff0c;同時&#xff0c;你也需要確保消息通信結構配置沒有遭受意外修改&#xff0c;從而避免應用消息丟失。RabbitMQ Management HTTP API提供了一個方法允許你查看任何vhost上的任何隊列&…

FFMpeg語法參數中文參考手冊

要查看你的ff mpeg支持哪些 格式&#xff0c;可以用如下命令&#xff1a;$ ffmpeg -formats | less還可以把 視頻文件導出成jpg序列幀&#xff1a;$ ffmpeg -i bc-cinematic-en.avi example.%d.jpgdebian下安裝ffmpeg很簡單&#xff1a;&#xff03;apt-get install ffmpegffmp…

Java類集框架 —— LinkedHashMap源碼分析

前言 我們知道HashMap底層是采用數組單向線性鏈表/紅黑樹來實現的&#xff0c;HashMap在擴容或者鏈表與紅黑樹轉換過程時可能會改變元素的位置和順序。如果需要保存元素存入或訪問的先后順序&#xff0c;那就需要采用LinkedHashMap了。 LinkedHashMap結構 LinkedHashMap繼承自H…

apache 支持.htaccess重寫url

1. httpd.conf 添加&#xff1a; <Directory />Options Indexes FollowSymLinks MultiviewsAllowOverride allRequire all grantedRewriteEngine On</Directory> 開啟&#xff1a; 在phpinfo里找到&#xff1a; 說明開啟成功。 2.httpd-vhosts.conf &#xff08;開…

oom 如何避免 高并發_【高并發】高并發環境下如何防止Tomcat內存溢出?看完我懂了!!...

【高并發】高并發環境下如何防止Tomcat內存溢出&#xff1f;看完我懂了&#xff01;&#xff01;發布時間&#xff1a;2020-04-19 00:47,瀏覽次數&#xff1a;126, 標簽&#xff1a;Tomcat寫在前面隨著系統并發量越來越高&#xff0c;Tomcat所占用的內存就會越來越大&#xff0…

[JSOI2008]最小生成樹計數

OJ題號&#xff1a;  BZOJ1016 題目大意&#xff1a;   給定一個無向帶權圖&#xff0c;求最小生成樹的個數。 思路&#xff1a;   先跑一遍最小生成樹&#xff0c;統計相同權值的邊出現的個數。   易證不同的最小生成樹&#xff0c;它們不同的那一部分邊的權值實際上是…

vuex webpack 配置_vue+webpack切換環境和打包之后服務器配置

import axios from ‘axios‘import store from ‘../store/index‘const rootUrl process.env.API_ROOT//創建axios實例const service axios.create({timeout:30000 //超時時間})//添加request攔截器service.interceptors.request.use(config >{if (Object.keys(config.hea…

redis基本用法學習(C#調用FreeRedis操作redis)

FreeRedis屬于常用的基于.net的redis客戶端&#xff0c;EasyCaching中也提供適配FreeRedis的包。根據參考文獻4中的說法&#xff0c;FreeRedis和CsRedis算是近親&#xff08;都是GitHub中賬號為2881099下的開源項目&#xff09;&#xff0c;因此其用法特別相似。FreeRedis的主要…

opencv:圖像的基本變換

0.概述 圖像變換的基本原理都是找到原圖和目標圖的像素位置的映射關系&#xff0c;這個可以用坐標系來思考&#xff0c;在opencv中&#xff0c; 圖像的坐標系是從左上角開始(0,0)&#xff0c;向右是x增加方向(cols)&#xff0c;向下時y增加方向(rows)。 普通坐標關系&#xff1…

FFMpeg在Windows環境下的編譯

1&#xff0e;安裝MinGW &#xff08;1&#xff09;下載文件&#xff1a;MinGW-5.1.4.exe&#xff0c; &#xff08;2&#xff09;安裝時選擇下列組件&#xff1a; binutils-2.19.1-mingw32-bin.tar.gz gcc-core-3.4.5-20060117-3.tar.gz gcc-g-3.4.5-20060117-3.tar.gz …

中通知設置響鈴_主動切斷干擾源——手機“通知”精細化管理

上周去參加我福福幼兒園的母親節活動&#xff0c;內容是孩子和家長一起穿手鏈。期間我發現和我同桌的一個家長的手機不停在響&#xff0c;當然伴隨著注意力被打斷。不僅是這位家長自己&#xff0c;連我也受到了干擾。于是職業病又犯了&#xff0c;我悄悄的看了一眼這位家長的手…

OCM_第十九天課程:Section9 —》Data Guard _ DATA GUARD 原理/DATA GUARD 應用/DATA GUARD 搭建...

注&#xff1a;本文為原著&#xff08;其內容來自 騰科教育培訓課堂&#xff09;。閱讀本文注意事項如下&#xff1a;1&#xff1a;所有文章的轉載請標注本文出處。2&#xff1a;本文非本人不得用于商業用途。違者將承當相應法律責任。3&#xff1a;該系列文章目錄列表&#xf…

python安裝各種插件

http://www.lfd.uci.edu/~gohlke/pythonlibs/#pip 感受&#xff1a;如果編輯pip真的一直出問題&#xff0c;考慮降成32位的進行安裝。畢竟合理搭配比木桶突出有用。轉載于:https://www.cnblogs.com/osmondwang/p/7307678.html

編寫數學公式的好工具

2019獨角獸企業重金招聘Python工程師標準>>> http://private.codecogs.com/latex/eqneditor.php 轉載于:https://my.oschina.net/yizhichao/blog/1542153

dev gridview 打印列數過多_R語言:如何將多張統計圖繪制在一張上面

在使用R語言進行數據可視化的時候&#xff0c;常常需要將多張統計圖表繪制在同一張圖上面&#xff0c;從而更高效地傳遞信息&#xff0c;下面我們就來一起看看具體如何實現。一、使用R語言自帶的函數繪制的圖像R語言本身就已經內置了許多繪圖函數&#xff0c;能夠滿足較為基本的…

264分析兩大利器 和 視頻系列下載:264VISA和Elecard StreamEye Tools

學了264有將近3個月有余&#xff0c;好多時候都在學習老畢的書和反復看JM86的代碼&#xff0c;最近才找到264分析兩大利器&#xff1a;264VISA和Elecard StreamEye Tools。不由得感嘆&#xff0c;恨不逢同時。 簡單的說下這兩個軟件&#xff1a; 264visa 強力的h264實時分析工具…

[轉]vue全面介紹--全家桶、項目實例

慢慢了解vue及其全家桶的過程 原文http://blog.csdn.net/zhenghao35791/article/details/67639415 簡介 “簡單卻不失優雅&#xff0c;小巧而不乏大匠”。 2016年最火的前端框架當屬Vue.js了&#xff0c;很多使用過vue的程序員這樣評價它&#xff0c;“vue.js兼具angular.js和R…

opencv 星空_opencv如何將大于5000像素點的輪廓繪制出來?

contourArea函數的運用。具體例子可以看下面的。《如何獲得物體的主要方向&#xff1f;》代碼略解&#xff1a;1、讀入圖片&#xff0c;尋找輪廓&#xff1b;//讀入圖像&#xff0c;轉換為灰度Mat img imread("e:/sandbox/pca1.jpg");Mat bw;cvtColor(img, bw, COLO…