H5直播系列八 FLV文件格式

如何看待嗶哩嗶哩的開源 HTML5 播放器內(nèi)核 flv.js?中,flv.js作者有這樣一段回復(fù):
一些人問(wèn)我為什么不直接采用 MP4 格式何陆,并表示對(duì) FLV 格式的厭惡甲献。這個(gè)問(wèn)題一方面是歷史遺留問(wèn)題晃洒,由于視頻網(wǎng)站前期完全依賴 Flash 播放而選擇 FLV 格式;另一方面吃引,如果仔細(xì)研究過(guò) FLV/MP4 封裝格式镊尺,你會(huì)發(fā)現(xiàn) FLV 格式非常簡(jiǎn)潔,而 MP4 內(nèi)部 box 種類繁雜弄砍,結(jié)構(gòu)復(fù)雜固實(shí)而又有太多冗余數(shù)據(jù)音婶。FLV 天生具備流式特征適合網(wǎng)絡(luò)流傳輸,而 MP4 這種使用最廣泛的存儲(chǔ)格式碴卧,設(shè)計(jì)卻并不一定優(yōu)雅螟深。

關(guān)于MP4格式,可以參考VillainHR 學(xué)好 MP4垢箕,讓直播更給力条获。本文來(lái)學(xué)習(xí)一下FLV格式。

參考
FLV文件格式詳解
flv格式詳解+實(shí)例剖析
FLV 實(shí)例分析

在集體挺進(jìn)HTML5的時(shí)代修档,來(lái)討論Adobe Flash相關(guān)的話題似乎有點(diǎn)過(guò)時(shí)吱窝,但現(xiàn)如今還是有很多的視頻網(wǎng)站采用的是Flash播放器,播放的文件也依然還有很多是FLV格式照激,而且僅從一個(gè)文件格式的角度去了解和分析FLV應(yīng)該也還說(shuō)的過(guò)去的实抡。FLV(Flash Video)是Adobe的一個(gè)免費(fèi)開放的音視頻格式吆寨,babala~~ 省略若干字的介紹,要看辣卒,到官網(wǎng)看吧想帅,這里不贅述港准,我們主要來(lái)討論下FLV文件格式的細(xì)節(jié),整體上衩椒,F(xiàn)LV分為HeaderBody兩大塊毛萌。

Header: 記錄FLV的類型朝聋,版本,當(dāng)前文件類型等信息言蛇,這些信息可以讓我們對(duì)當(dāng)前FLV文件有個(gè)概括的了解腊尚。

Body: FLV的Body是Flv的數(shù)據(jù)區(qū)域,這些是FLV的具體內(nèi)容民宿,因?yàn)镕LV中的內(nèi)容有多種活鹰,并可同時(shí)存在着绷,因此,Body也不是一整塊的數(shù)據(jù)子漩,而是由更細(xì)分的塊來(lái)組成,這個(gè)細(xì)分的塊叫Tag讲衫。


image.png

先來(lái)一張圖,這是《東風(fēng)破》——周杰倫(下載)的一個(gè)MV視頻枷畏。我使用的是Binary Viewer的二進(jìn)制查看工具拥诡。

image.png

一、Header

頭部分由一下幾部分組成仇祭,Signature(3 Byte)+Version(1 Byte)+Flags(1 Bypte)+DataOffset(4 Byte)乌奇,共9字節(jié)。
1.signature
46 4C 56 正是FLV這三個(gè)字符的ASCII編碼困乒,這個(gè)是固定標(biāo)識(shí)迁霎,表示它是FLV文件考廉。
2.version
版本號(hào)0x01
3.Flags
0x05既绕,對(duì)應(yīng)二進(jìn)制00000101凄贩,前面一個(gè)1表示有音頻數(shù)據(jù)疲扎,后面一個(gè)1表示有視頻數(shù)據(jù)。
4.DataOffset
此4字節(jié)共同組成一個(gè)無(wú)符號(hào)32位整數(shù)(使用大頭序)救巷,表示文件從FLV Header開始到Flv Body的字節(jié)數(shù)棒假,當(dāng)前版本固定為9(0x00,0x00渤弛,0x00佳头,0x09)

二康嘉、Body

1.Previous Tag Size
這個(gè)比較好理解亭珍,就是前一個(gè)Tag的大小阻荒,這里同樣存的是無(wú)符號(hào)32位整型數(shù)值侨赡。因?yàn)榈谝粋€(gè)Previous Tag Size是緊接著FLV Header的,因此油猫,其值也是固定為0(0x00眨攘,0x00,0x00该肴,0x00)匀哄。

2.TAG
FLV中的TAG不止一種涎嚼,當(dāng)前版本共有3種類型組成:音頻(audio),視頻(video)立哑,腳本數(shù)據(jù)(script data),這三種類型會(huì)在Tag內(nèi)進(jìn)行標(biāo)志區(qū)分捂掰。其中:Audio Tag是音頻數(shù)據(jù)这嚣,Video Tag是視頻數(shù)據(jù)互广,Script Data存放的是關(guān)于FLV視頻和音頻的一些參數(shù)信息(亦稱為Metadata Tag),通常該Tag會(huì)在FLV File Header后面作為第一個(gè)Tag出現(xiàn)旅敷,并且一個(gè)文件僅有一個(gè)Script Data Tag。

為了在Tag內(nèi)存放不同的數(shù)據(jù)晴音,并且能夠方便區(qū)分锤躁,每個(gè)Tag被定義了Tag Header和Tag Data兩部分,他們的結(jié)構(gòu)如下:

-------------------------
|       Tag Header      |
-------------------------
|       Tag  Data       |
-------------------------
 
 
 
                -------------------------
                |       Tag Header      |
                -------------------------
                 /                    \
--------------------------------------------------------
| 08 | 00 | 00 | 18 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
--------------------------------------------------------

Tag Header由11字節(jié)組成:

  • 第1字節(jié)type:標(biāo)志當(dāng)前Tag的類型,音頻(0x08)梧乘,視頻(0x09)澎迎,Script Data(0x12),除此之外选调,其他值非法嗡善;
  • 第2-4字節(jié)tag data size:表示一個(gè)無(wú)符號(hào)24位整型數(shù)值,表示當(dāng)前Tag Data的大醒纭罩引;
  • 第5-7字節(jié)Timestreamp:無(wú)符號(hào)24位整型數(shù)值(UI24),當(dāng)前Tag的時(shí)間戳(單位為ms)枝笨,第一個(gè)Tag的時(shí)間戳總為0;
  • 第8字節(jié)TimestampExtended:為時(shí)間戳的擴(kuò)展字節(jié)洒缀,當(dāng)前24位不夠用時(shí),該字節(jié)作為最高位瘫俊,將時(shí)間戳擴(kuò)展為32位無(wú)符號(hào)整數(shù)(UI32)
  • 第9-11字節(jié)stream id:UI24類型川尖,表示Stream ID,總是0

看一下上述實(shí)例,第一個(gè)TAG:

type=0x12=18毛嫉,是一個(gè)Script Data仙粱。
tag data size=0x000125=293。長(zhǎng)度為293。
timestreamp=0x000000。這里是scripts楔脯,所以為0
TimestampExtended =0x00皆串。
stream id =0x000000

這里來(lái)找一下第一個(gè)TAG在哪里結(jié)束姥宝,Tag Header本身是11個(gè)字節(jié)漱凝,第2-4字節(jié)tag data size現(xiàn)在已經(jīng)知道是293字節(jié),合計(jì)第一個(gè)TAB長(zhǎng)度是11+293=304也就是16進(jìn)制的130快耿。那么下一個(gè)TAG的Previous Tag Size應(yīng)該就是0x 00 00 01 30吮便,見下圖紅線


image.png

可以在圖片上數(shù)一下,第一行的12 00 01是3個(gè),中間共18行,每行16字節(jié)宫蛆,最后劃紅線00 00 01那行有13字節(jié),合計(jì)是3+18*16+13=304,確認(rèn)無(wú)誤肴颊。

3.TAG DATA
Tag Data由Tag Header標(biāo)志后,就被分成音頻闯睹,視頻荣挨,Script Data三類

4.Script Data
腳本Tag一般只有一個(gè),是flv的第一個(gè)Tag,用于存放flv的信息,比如duration缚陷、audiodatarate非春、creator禽炬、width等。

首先介紹下腳本的數(shù)據(jù)類型。所有數(shù)據(jù)都是以數(shù)據(jù)類型+(數(shù)據(jù)長(zhǎng)度)+數(shù)據(jù)的格式出現(xiàn)的拒迅,數(shù)據(jù)類型占1byte蒙揣,數(shù)據(jù)長(zhǎng)度看數(shù)據(jù)類型是否存在,后面才是數(shù)據(jù)办龄。

image.png

image.png

image.png

string類型會(huì)先用uint16 標(biāo)識(shí)出數(shù)據(jù)長(zhǎng)度

image.png

image.png

一般來(lái)說(shuō),該Tag Data結(jié)構(gòu)包含兩個(gè)AMF包昼榛。AMF(Action Message Format)是Adobe設(shè)計(jì)的一種通用數(shù)據(jù)封裝格式境肾,在Adobe的很多產(chǎn)品中應(yīng)用,簡(jiǎn)單來(lái)說(shuō)胆屿,AMF將不同類型的數(shù)據(jù)用統(tǒng)一的格式來(lái)描述奥喻。第一個(gè)AMF包封裝字符串類型數(shù)據(jù),用來(lái)裝入一個(gè)“onMetaData”標(biāo)志非迹,這個(gè)標(biāo)志與Adobe的一些API調(diào)用有环鲤,在此不細(xì)述。第二個(gè)AMF包封裝一個(gè)數(shù)組類型憎兽,這個(gè)數(shù)組中包含了音視頻信息項(xiàng)的名稱和值冷离。具體說(shuō)明如下,大家可以參照?qǐng)D片上的數(shù)據(jù)進(jìn)行理解纯命。

(1)先看第一個(gè)AMF包西剥,從02 00 0A 6F往后讀
第一個(gè)域是Name。Name又是SCRIPTDATAVALUE類型
type = 0x 02 對(duì)照上表是SCRIPTDATASTRING
SCRIPTDATASTRING類型會(huì)先用uint16標(biāo)識(shí)出數(shù)據(jù)長(zhǎng)度
size = 0x 00 0A 亿汞,說(shuō)明長(zhǎng)度為10
value=onMeta Data= 0x 6F 6E 4D 65 74 61 44 61 74 61對(duì)應(yīng)的ASCII碼正是onMetaData瞭空,見下圖紅線。

image.png

(2)然后看第二個(gè)AMF
type = 0x 08 對(duì)照上表是數(shù)組疗我,后面Length UI32匙铡,即4個(gè)字節(jié)為數(shù)組的個(gè)數(shù)
size = 0x 00 00 00 0D = 13,說(shuō)明數(shù)組長(zhǎng)度為13碍粥,后面有13個(gè)SCRIPTDATAOBJECTPROPERTY鳖眼。
對(duì)照上圖,SCRIPTDATAOBJECTPROPERTY由PropertyName(SCRIPTDATASTRING類型)和PropertyData(SCRIPTDATAVAULE類型)組成

(3)第一個(gè)鍵值對(duì)
PropertyName 是SCRIPTDATASTRING類型
string length = 0x 00 08 說(shuō)明長(zhǎng)度為8
string data= 0x 64 75 72 61 74 69 6F 6E嚼摩,正是ASCII碼duration

PropertyData是一個(gè)SCRIPTDATAVAULE類型钦讳。用的是UI8標(biāo)識(shí)type
type = 0x 00 是個(gè)double數(shù)值(8字節(jié))
value = 0x 40 73 A7 85 1E B8 51 EC

(4)第二個(gè)鍵值對(duì)
PropertyName 是SCRIPTDATASTRING類型
string length = 0x 00 05 說(shuō)明長(zhǎng)度為5
string data = 0x 77 69 64 74 68矿瘦,正是ASCII碼width

PropertyData是一個(gè)SCRIPTDATAVAULE類型。用的是UI8標(biāo)識(shí)type
type = 0x 00 是個(gè)double數(shù)值(8字節(jié))
value = 0x 40 76 00 00 00 00 00 00

(5)第三個(gè)鍵值對(duì)
PropertyName
string length = 0x 00 06 長(zhǎng)度為6
string data = 68 65 69 64 74 68 即width

PropertyData
type = 0x 00
value = 0x 40 76 00 00 00 00 00 00

后面的屬性同理

5.video tag


image.png

type=0x09=9愿卒。這里應(yīng)該是一個(gè)video缚去。
size=0x000030=48。長(zhǎng)度為48琼开。
timestreamp=0x000000易结。
TimestampExtended =0x00。
stream id =0x000000

(1)接著StreamID字段之后的就是VideoTAagHeader


image.png

特殊情況
視頻的格式(CodecID)是AVC(H.264)的話柜候,VideoTagHeader會(huì)多出4個(gè)字節(jié)的信息搞动,AVCPacketType 和CompositionTime。

AVCPacketType 占1個(gè)字節(jié)

類型
0 AVCDecoderConfigurationRecord(AVC sequence header)
1 AVC NALU
2 AVC end of sequence (lower level NALU sequence ender is not required or supported)

AVCDecoderConfigurationRecord.包含著是H.264解碼相關(guān)比較重要的sps和pps信息渣刷,再給AVC解碼器送數(shù)據(jù)流之前一定要把sps和pps信息送出鹦肿,否則的話解碼器不能正常解碼。而且在解碼器stop之后再次start之前辅柴,如seek箩溃、快進(jìn)快退狀態(tài)切換等,都需要重新送一遍sps和pps的信息.AVCDecoderConfigurationRecord在FLV文件中一般情況也是出現(xiàn)1次碌嘀,也就是第一個(gè)video tag.

CompositionTime 占3個(gè)字節(jié)

條件
AVCPacketType ==1 Composition time offset
AVCPacketType !=1 0

(2)第一個(gè)字節(jié)是0x 17涣旨,即
FrameType= 0x01
CodecID = 0x07
因?yàn)閏odecID=7,所以后面有AVCPacketType1個(gè)字節(jié)=0,CompositionTime3個(gè)字節(jié)也是0股冗。

(3)我們看第一個(gè)video tag开泽,也就是前面那張圖。我們看到AVCPacketType =0魁瞪。而后面三個(gè)字節(jié)也是0穆律。說(shuō)明這個(gè)tag記錄的是AVCDecoderConfigurationRecord。包含sps和pps數(shù)據(jù)导俘。

image.png

下面為了復(fù)制截圖方便峦耘,引用了FLV 實(shí)例分析中的例子
image.png

configurationVersion = 0x01
AVCProfileIndication = 0x4D (77) Main Profile
profile_compatibiltity = 0x40
AVCLevelIndication = 0x1F (31)
第五六字節(jié)是0xFFE1 ,寫成二進(jìn)制格式 ‘1111 1111 1110 0001’b
對(duì)應(yīng)到AVCDecoderConfigurationRecord的語(yǔ)法定義
lengthSizeMinusOne = ‘11’b (3) 也就是NALUintLength字段會(huì)是4個(gè)字節(jié)
numOfSequenceParameterSets = ‘00001’b 有一個(gè)Sps結(jié)構(gòu)
接下來(lái)16bits 是 sequenceParameterSetLength = 0x0019 (25 bytes)
下圖選中部分就是Sps了
image.png

再往下:
numOfPictureParamterSets = 0x01
pictureParameterSetLength = 0x0004;
下圖選中的就是pps了
image.png

再后面四個(gè)字節(jié)是PreviousTagSize= 0x00 00 00 38 (56) 等于這個(gè)Tag的 DataSize + 11 == (45) + 11。

6.audio tag
再下來(lái)又是一個(gè)新的FLVTAG了旅薄。
11個(gè)字節(jié)的頭部先取出來(lái)
TagType = 8 (音頻)
DataSize =0x000009 ( 9bytes)

(1)AudioTagHeader結(jié)構(gòu) 0xAF
SoundFormat(4bits) = 0x0A (10 == AAC)
SoundRate(2bits) = ‘11’b (3 == 44kHz)
SoundSize(1bit) =’1’b (1 == 16-bit)
SoundType(1bit) = ‘1’b (1= Stereo)
注: 雖然這里SoundRate, SoundSize SoundType 都是 1 辅髓。但是這些都是定值,AAC格式的時(shí)候少梁,不看這里的值洛口,可以忽略掉。具體的真是值應(yīng)該從后面的數(shù)據(jù)從獲取
AACPacketType == 0x00 (AAC seqence header)
所以AACPacketType后面的就是AudioSpecificConfig了 0x13 90 56
AudioSpecificConfig.audioObjectType(5 bits) = 2 (AAC LC)
AudioSpecificConfig.samplingFrequencyIndex(4 bits) = 7
AudioSpecificConfig.channelConfiguration (4 bits)= 2
AudioSpecificConfig.GASpecificConfig.frameLengthFlag (1 bit) = 0
AudioSpecificConfig.GASpecificConfig.dependsOnCoreCoder : (1 bit) = 0
AudioSpecificConfig.GASpecificConfig.extensionFlag : (1 bit) = 1
剩下的四個(gè)字節(jié)就是extensionflag3的相關(guān)內(nèi)容凯沪,這塊還沒(méi)有研究過(guò)第焰。
到這一個(gè)audioTag結(jié)束。
后面的0x00000014是這個(gè)AudioTag的長(zhǎng)度 等于 20 = 9 + 11妨马。

7.再后面又是一個(gè)新的TAG


image.png

從這前11個(gè)字節(jié)知道的是這是一個(gè)視頻Tag. DataSize = 0x00099F (2463)timeStamp == 0挺举;
然后再往后看杀赢,是一個(gè)VideoTagHeader結(jié)構(gòu),可以得到的信息如下
FrameType = 1 (是一個(gè)Key Frame)
CodecID= 7 (AVC)
AVCPacketType = 1 湘纵;是一個(gè)普通的AVC NALUint
CompositionTime = 0x000043 (67)
那么這個(gè)Key Frame包含多少個(gè)NALUint呢脂崔,我們?cè)賮?lái)一步步看下去吧。記得前面我們分析的嗎梧喷?NALUint數(shù)據(jù)的開頭的NALUintLength字段砌左。由之前的分析可知。占四個(gè)字節(jié)铺敌,
NALUintLength = 0x00000222 (546 Bytes) 說(shuō)明第一NALUint的長(zhǎng)度是546字節(jié)


選中的546字節(jié)

接著是第二個(gè)NALUintLength = 0x00 00 05 F3 (1523 bytes) 汇歹,圖片太長(zhǎng),詳見原文
接下來(lái)又是一個(gè)NALUintLength = 0x00 00 01 0B (267 bytes) 适刀,圖略
下來(lái)又是一個(gè)NALUintLenth = 0x00 00 00 32 (50 bytes) 秤朗,圖略
接下來(lái)還是一個(gè)NALUintLength = 0x00 00 00 34 (52 byte)煤蹭,圖略

好了笔喉,到這里我們第一個(gè)KeyFrame的所有NALUint都已經(jīng)取出來(lái)了 ,TagDataSize (2463 Bytes)= 1 (FrameType + CodecID) + 1 (AVCPacketType) + 3 (CompositionTime) + 4 + 546 +4 + 1523 + 4 + 267 + 4 + 50 + 4 + 52 等式成立硝皂。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末常挚,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子稽物,更是在濱河造成了極大的恐慌奄毡,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,273評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贝或,死亡現(xiàn)場(chǎng)離奇詭異吼过,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)咪奖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門盗忱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人羊赵,你說(shuō)我怎么就攤上這事趟佃。” “怎么了昧捷?”我有些...
    開封第一講書人閱讀 167,709評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵闲昭,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我靡挥,道長(zhǎng)序矩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,520評(píng)論 1 296
  • 正文 為了忘掉前任跋破,我火速辦了婚禮贮泞,結(jié)果婚禮上楞慈,老公的妹妹穿的比我還像新娘。我一直安慰自己啃擦,他們只是感情好囊蓝,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著令蛉,像睡著了一般聚霜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上珠叔,一...
    開封第一講書人閱讀 52,158評(píng)論 1 308
  • 那天蝎宇,我揣著相機(jī)與錄音,去河邊找鬼祷安。 笑死姥芥,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的汇鞭。 我是一名探鬼主播凉唐,決...
    沈念sama閱讀 40,755評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼霍骄!你這毒婦竟也來(lái)了台囱?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,660評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤读整,失蹤者是張志新(化名)和其女友劉穎簿训,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體米间,經(jīng)...
    沈念sama閱讀 46,203評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡强品,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了屈糊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片的榛。...
    茶點(diǎn)故事閱讀 40,427評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖另玖,靈堂內(nèi)的尸體忽然破棺而出困曙,到底是詐尸還是另有隱情,我是刑警寧澤谦去,帶...
    沈念sama閱讀 36,122評(píng)論 5 349
  • 正文 年R本政府宣布慷丽,位于F島的核電站,受9級(jí)特大地震影響鳄哭,放射性物質(zhì)發(fā)生泄漏要糊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評(píng)論 3 333
  • 文/蒙蒙 一妆丘、第九天 我趴在偏房一處隱蔽的房頂上張望锄俄。 院中可真熱鬧局劲,春花似錦、人聲如沸奶赠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)毅戈。三九已至苹丸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間苇经,已是汗流浹背赘理。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留扇单,地道東北人商模。 一個(gè)月前我還...
    沈念sama閱讀 48,808評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像蜘澜,于是被迫代替她去往敵國(guó)和親施流。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容