YOMEDIA
ADSENSE
Lược đồ mã hóa MPEG hình ảnh động theo chuẩn lưu trữ số -2
93
lượt xem 7
download
lượt xem 7
download
Download
Vui lòng tải xuống để xem tài liệu đầy đủ
- Layer I : 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256 kbps Những tốc độ này là có thể ở chế độ Mono hay stereo.. - Layer II : 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 kbps. Những tốc độ này là có thể ở chế độ Mono hay stereo. d. Layers. Chuẩn MPEG có ba layer. Khi chọn lựa tốc độ bit cần xem xét các vấn đề: Ở cùng tốc độ bit, Layer II mang lại chất lượng âm thanh tốt hơn Layer I. Kết...
AMBIENT/
Chủ đề:
Bình luận(0) Đăng nhập để gửi bình luận!
Nội dung Text: Lược đồ mã hóa MPEG hình ảnh động theo chuẩn lưu trữ số -2
- 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 kbps. 32, 48, 56, 80 kbps chỉ có thể ở chế độ Mono; 64, 96, 112, 128, 160, 192 kbps có thể ở cả hai chế độ Mono và Stereo;224, 256, 320, 384 kbps ch ỉ có thể ở chế độ Stereo. • MPEG 2 : 16 kHz, 22.05 kHz và 24 kHz - Layer I : 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256 kbps Những tốc độ n ày là có thể ở chế độ Mono hay stereo.. - Layer II : 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 kbps. Những tốc độ n ày là có thể ở chế độ Mono hay stereo. d. Layers. Chu ẩn MPEG có ba layer. Khi chọn lựa tốc độ bit cần xem xét các vấn đề: Ở cùng tốc độ bit, Layer II mang lại chất lượng âm thanh tốt h ơn Layer I. • Kết luận này là chủ quan, vì sự chênh lệch là rất khó phân biệt ở tốc độ bit 128 kbps và lớn hơn. Dùng Layer I thì việc chọn lọc chính xác hơn Layer II b ởi vì độ phân giải • của Layer I gấp ba lần Layer II. Resolution Table Sampling frequency Layer I (384 samples) Layer II (1152 samples)
- 32 kHz 12 ms 36 ms 44.1 kHz # 8.71 ms # 26.12 ms 48 kHz 8 ms 24 ms 16 kHz 24 ms 72 ms 22.05 kHz # 17.42 ms # 52.24 ms 24 kHz 16 ms 48 ms Các điểm kỹ thuật mấu chốt. Chu ẩn mã hóa âm thanh MPEG chỉ định việc ghi một số cố định các mẫu (384 cho Layer I và 1152 cho Layer II) đ ể tạo ra một chuỗi các bytes gọi là “frame”. “Frame” là thực thể nhỏ nhất được điều khiển bởi một ứng dụng. Việc chọn tốc độ bit(kbps) thiết lập nên kích thước của frame đó theo byte. Ví dụ: Ở 48 kHz, 128 kbps, chế độ Mono, Layer II: 48,000 m ẫu, tương ứng 1000 ms hay 1s, 1152 mẫu tương ứng 24 ms. • Ở tốc độ bit 128,000 bits/s, 3072 bits (384 bytes) cần cho 24 ms. • Chiều d ài frame vì thế là 384 byte. • Để lưu 1 phút, cần 960,000 byte (hay khoảng 1 Megabyte) đĩa trống. • CHƯƠNG 5. CÁC GIẢI THUẬT NÉN ÂM THANH. I. NỀN TẢNG LÝ THUYẾT THÔNG TIN. Theo Shannon, entropy của một nguồn thông tin S được định nghĩa: H(S) =ipilog2(1/pi) Trong đó: - p i là xác suất m à ký hiệu Si xuất hiện trong S. - log2(1/pi) ch ỉ ra số lượng thông tin chứa đựng trong Si, nghĩa là số bit cần thiết để m ã hóa Si.
- Ví dụ: một hình ảnh đ ược tô đều với cùng một cường độ m àu xám, tức là • pi=1/256, thì số bit cần thiết để m ã hóa cho mỗi mức xám là 8 bits. Entropy của hình này là 8. Giải thuật Sh annon - Fano: Ta dùng một ví dụ đơn giản để mô tả giải thuật: Ký hiệu A B C D E --------------------------------------------------- Số lần 15 7 6 6 5 Mã hóa cho giải thuật Shannon - Fano: Dùng cách tiếp cận từ trên xuống. Sắp thứ tự các ký hiệu theo tần số xuất hiện của nó, nghĩa là: ABCDE. • Chia thành hai phần, mỗi phần tương đương với cùng số lần đếm. • Hình 5.1 Ký hiệu Số lần Cộng(số bit) log(1/p) Mã ---------- -------- ---------- ----- --------------- A 15 1.38 00 30 B 7 2.48 01 14 C 6 2.70 10 12 D 6 2.70110 18 E 5 2.96111 15 Tổng cộng(số bit) : 89 II. CÁC GIẢI THUẬT NÉN KHÔNG CÓ TỔN THẤT. 1. Mã hóa Huffman.
- Khởi tạo: đưa tất cả các node vào danh sách OPEN theo thứ tự tại mọi thời • điểm. Ví dụ: ABCDE. Lặp lại cho đến khi danh sách OPEN chỉ còn một node bên trái như sau: • - Từ danh sách OPEN, chọn hai node có xác suất thấp nhất, tạo node cha cho chúng. - Gán tổn g các xác suất cho node cha và đưa node cha vào danh sách OPEN. - Gán các mã 0, 1 vào các nhánh của cây, xóa các node con khỏi danh sách OPEN. Hình 5.2 Ký hiệu Số lần Cộng(số bit) log(1/p) Mã ---------- --------- ---------- ----- --------------- A 15 1.38 0 30 B 7 2.48 100 14 C 6 2.70 101 12 D 6 2.70 110 18 E 5 2.96 111 15 Tổng cộng (số bit) : 87 Việc giải m ã cho cả hai giải thuật trên là tầm thường chừng nào mà bảng mã • (thống kê) được gửi trước dữ liệu. Có một bit b ên trên công việc truyền n ày, nhưng không đáng kể nếu file dữ liệu lớn. Tính chất tiền tố duy nhất: không có mã nào là tiền tố cho một mã khác (tất • cả các ký hiệu đều là node lá) rõ ràng là lớn đối với bộ giải mã. Nếu việc thống kê có thể tiến hành được trước đó và với độ chính xác cao, • thì mã Huffman là rất tốt. Trong ví dụ trên:Entropy=(15x1.38+7x2.48+ 6x2.7 + 6x2.7 + 5x2.96)/39
- = 85.26 / 39 = 2.19. Số bit cần thiết cho m ã hóa Huffman là : 87 / 39 = 2.23 2. Mã Huffman sửa đổi. (a) Các giải thuật trên đây yêu cầu kiến thức về thống kê là điều mà khó có thể thực hiện (ví dụ âm thanh, hình ảnh sống..). (b) Ngay cả khi nếu điều đó là có thể làm được thì chi phí cho nó khá nặng, đặc biệt khi có nhiều bảng phải được truyền mà mô hình non-order() được sử dụng, nghĩa là việc đưa vào tính toán sự ảnh hưởng của các ký hiệu trước đó với xác suất của ký hiệu hiện h ành (ví dụ: “qu” thường đi với nhau,..). Giải pháp đưa ra là dùng giải thuật sửa đổi cho thích hợp. Như ví dụ, việc m ã hóa Huffman sửa đổi được khảo sát sau đây với ý tưởng là làm thế nào có th ể áp dụng vào các giải thuật nén thích hợp khác. Mấu chốt ở đây là cả hai bộ m ã hóa và giải m ã đ ều dùng cùng các hàm • Initialize_model và update_model . Hàm update_model có hai lưu ý: (a) Tăng biến đếm. • (b) Cập nhật cây Huffman. - Trong suốt qúa trình cập nhật, cây Huffman sẽ được duy trì tính kế thừa, các nodes (node trong và lá) được sắp xếp theo thứ tự tăng dần của trọng lượng . - Khi cần thiết trao đổi (swapping), node xa nhất với trọng lượng W đ ược trao đổi với node mà trọng lư ợng của nó tăng lên 1 đơn vị W+1. Lưu ý: nếu node trọng lượng W có cây con bên dư ới nó thì cây con đó cũng phải dời cùng với nó. Cây Huffman có th ể nhìn rất khác so với trước khi trao đổi, ví dụ trong cây thứ 3 , node A được trao đổi và trở th ành node 5. Bây giờ nó được m ã hóa chi bằng 2 bit.
- 3. Mã hóa số học. Mã hóa Huffman sử dụng một số nguyên k các bit cho mỗi ký hiệu, vì th ế k không bao giờ nhỏ hơn 1. Đôi khi, ví dụ phải truyền một h ình ảnh 1 bit, thì không th ể nén được. Ý tưởng: giả sử mẫu tự là [X,Y] và P(X) = 2/3 P(Y) = 1/3. Nếu ta chỉ quan tâm với chiều dài mã hóa là 2 thông điệp, th ì ta có th ể ánh • xạ tất cả thông điệp có thể có vào những đoạn trong phạm vi [0..1] Để m ã hóa thông điệp, chỉ dùng vừa đủ số bit cần thiết cho mỗi đoạn. • Tương tự, ta có thể ánh xạ tất cả chiều d ài 3 thông điệp vào các đoạn trong • [0..1]. Nói chung, số bit được xác định bằng kích thước của đoạn. • Ví dụ: Đoạn đầu tiên là 8/27, cần 2 bit 2/3 b it cho mỗi ký tự. Đoạn cuối là 1/27, cần 5 bit. Tóm lại, cần -[logp] bit để biểu diễn cho đoạn có kích thước p. • Vấn đề đặt ra là làm thế n ào để xác định được xác suất? • Ý tưởng đ ơn giản là dùng mô phỏng: bắt đầu bằng việc đoán tần số của một ký hiệu. Cập nhật tần số cho mỗi ký hiệu mới. 4. Giải thuật Lempel-Ziv-Welch(LZW). Giả sử chúng ta muốn mã hóa cho một cuốn tự điển Tiếng Anh 159,000 từ. Như vậy mỗi từ cần 18 bit để mã hóa. Nhược: - Dùng qúa nhiều bit. - Chỉ làm việc cho ký tự tiếng Anh.
- Giải pháp: - Cần phải tìm một cách m ã hóa cuốn từ điển cho thích hợp. - Các phương pháp ban đ ầu đ ược đề xuất bởi Ziv và Lempel vào năm 1978 và 1979. Terry Welch phát triển lư ợc đồ vào năm 1981 và trở thành giải thuật LZW. Giải thuật: w = NIL; while (read a character k) { if wk exists in the dictionary w = wk; else add wk to the dictionary; output the code for w; w = k; } LZW nguyên gốc sử dụng từ điển với 4K mục từ, 256 từ đầu tiên là mã ASCII. Ví dụ: chuỗi ký tự là “^WED^WE^WEE^WEB^WET”. w k output index symbol ------------------------------------------------------------------ NIL ^ ^ W ^ 256 ^W W E W 257 WE E D E 258 ED D ^ D 259 D^ ^ W ^W E 256 260 ^WE E ^ E 261 E^
- ^ W ^W E ^WE E 260 262 ^WEE E ^ E^ W 261 263 E^W W E WE B 257 264 WEB B ^ B 265 B^ ^ W ^W E ^WE T 260 266 ^WET T EOF T 19 ký hiệu nhập đ ược giảm xuống 7 ký tự và 5 mã. Mỗi mã/ký hiệu sẽ cần nhiều hơn 8 bit, ta lấy 9 bit. Thông thường, công việc nén chỉ đư ợc bắt đầu khi có một số lớn byte đ ược đọc vào (ví dụ >100). Giải thuật giải nén LZW: read a character k; output k; w = k; while ( read a character k ) /* k could be a character or a code. */ {entry = dictionary entry for k; output entry; add w + entry[0] to dictionary;
- w = entry;} III. CÁC GIẢI THUẬT NÉN CÓ TỔN THẤT. 1. Các phương pháp nén âm thanh đơn giản: Các phương pháp nén khảo sát ở trên không hiệu quả trong việc nén âm • thanh. Sau đây là các phương pháp nén có tổn thất: • - Nén “silence” : dò các khoảng “yên lặng”, giống như m ã hoá run -length. - LPC (Linear Predictive Coding). - CELP (Code Excited Linear Predictor). 2. Nén âm thanh dùng mô hình ââm - tâm lý. a. Hệ thống nghe và phát âm của con người. Ph ạm vi nghe đ ược từ 20 Hz đến 20 kHz, nhạy cảm ở 2 - 5 kHz. • Ph ạm vi phát âm b ình thường từ 500 Hz đến 2 kHz. • b. Che tần số (Frequency masking) “Ngưỡng che” (Threshold masking): sinh ra từ hiệu ứng che, mỗi âm với một tần số và mức to (dB) xác định sẽ có một “ngưỡng che” (xem hình 4.3 và 4.4) c. Băng giới hạn. Thước đo tần số đồng bộ không tương xứng với độ rộng của đường cong • che. Băng giới hạn có độ rộng là 100Hz đối với các tần số che < 500Hz, và càng • tăng lên đối với các tần số >500Hz. Định nghĩa một đơn vị mới cho tần số là bark ( Barkhausen) • 1 Bark = bề rộng của băng giới hạn: - Tần số
- - Tần số >500Hz : 1 bark = 9 + 4log(freq/1000). Ngưỡng che trên thước đo băng giới hạn: • Hình 5.3 d. Che nhất thời (Temporal masking): che theo thời gian. Tai người cũng có đặc tính lưu âm. Nếu có một âm thanh lớn, rồi ngưng nó lại, m ãi một lúc sau ta mới có thể nghe được một âm lân cận nhỏ h ơn (xem hình 4.5 và 4.6). 3. Nén âm thanh MPEG. Vài thông số: MPEG-1 : 1.5Mbits/s cho âm thanh và hình ảnh. • Kho ảng 1.2 Mbits cho hình ảnh và 0.3Mbits/s cho âm thanh. Aâm thanh CD không nén dùng: (44,100 mẫu/s * 16bit/mẫu * 2 kênh) > 1.4 Mbits/s Aâm thanh MPEG cung cấp các tần số lấy mẫu là 32, 44.1 và 48 kHz. • Giải thuật: • Dùng bộ lọc thông để chia tín hiệu âm thanh thành các sub -band theo tần số, 1. tương ứng với 32 băng giới hạn lọc sub -band. Xác định số lượng che của mỗi band gây bởi các band lân cận bằng các kết 2. qủa bước 1 mô hình âm - tâm lý. Nếu mức to của một băng mà nhỏ h ơn ngưỡng che th ì không mã hóa nó. 3. Ngược lại, xác định số bit cần thiết để m ã hóa sao cho nhiễu sinh ra bởi việc 4. lượng tử hóa này th ấp hơn đường cong che. 5. Định dạng dòng dữ liệu bit : Hình 5.4
- Ví dụ: Sau khi phân tích, 16 band đầu tiên trong số 32 band như sau: _________________________________________________________ Band 12 3 4 56 7 89 10 11 12 13 14 15 16 Level(dB) 0 8 12 10 6 2 10 60 35 20 15 2 3 531 _________________________________________________________ Nếu mức to của âm thứ 8 là 60dB, nó sẽ che band thứ 7 ở mức 12dB và band • thứ 9 ở mức 15dB. Mức to ở band 7 là 10dB ( 15dB) nên được tiếp tục xử lý. Layer I: b ộ lọc loại DCT với 1 frame và độ rộng tần số như nhau trên mỗi • sub-band. Mô hình âm-tâm lý chỉ sử dụng hiệu quả che tần số (Frequency masking). Layer II: sử dụng 3 frame trong bộ lọc (trước, hiện tại và kế tiếp, tổng cộng • 1152 mẫu). Mô hình âm -tâm lý có sử dụng hiệu quả che nhất thời (Temporal masking). Layer III: dùng bộ lọc băng giới hạn tốt hơn, mô hình âm-tâm lý có sử dụng • hiệu quả che nhất thời, và có dùng bộ mã hoá Huffman. Ph ần II THIẾT KẾ CHƯƠNG TRÌNH CHƯƠNG 6. LƯU ĐỒ GIẢI THUẬT VÀ CẤU TRÚC DỮ LIỆU. I. SƠ ĐỒ KHỐI. II. CẤU TRÚC DỮ LIỆU VÀ ĐỊNH NGHĨA. A. Cấu trúc dữ liệu. 1. Các cấu trúc về file:
- - Tập tin tiêu đ ề : - Sử dụng : truy xuất các tập tin dạng *.wav và *.mp3. Trong chương trình, các cấu trúc này sử dụng ở các giai đoạn mở file, đọc cấu h ình file, truy xuất các thông tin về cấu hình file. a. Cấu trúc FILE WAVE : typedef struct { FILE *file; int type; int channels; int bits; long samplerate; long total_samples; long length; } wave_t; b. Cấu trúc FILE MPEG: typedef struct { FILE *file; int type; int layr; int mode; int bitr; int psyc; int emph; int padding;
- long samples_per_frame; long bits_per_frame; long bits_per_slot; long total_frames; int bitrate_index; int samplerate_index; int crc; int ext; int mode_ext; int copyright; int original; int mode_gr; } mpeg_t; c. Cấu trúc config_t : typedef struct { time_t start_time; char* infile; wave_t wave; char* outfile; mpeg_t mpeg; } config_t; 2. Cấu trúc dòng bit d ữ liệu: bitstream_t - Tập tin tiêu đ ề :
- - Sử dụng: d ùng trong quá trình đọc hoặc ghi dữ liệu từ file lên vùng đệm và ngược lại. typedef struct bit_stream_struc { /* con trỏ đến file bit dữ liệu */ FILE *pt; /* vùng đ ệm cho dòng bit dữ liệu */ unsigned char *buf; /* kích thước vùng đệm tính theo số byte */ int buf_size; /* đếm bit */ long totbit; /* ch ỉ byte trên cùng trong vùng đệm */ int buf_byte_idx; /* bit trên cùng của byte trên cùng trong vùng đệm */ int buf_bit_idx; /* mở dòng bit ở chế độ đọc hay ghi */ int mode; /* ch ỉ đến cuối vùng đệm */ int eob; /* đầu cuối của cờ dòng bit */ int eobs; /* định dạng file ở chế độ đọc (BINARY/ASCII) */ char format; } bitstream_t; 3. Các cấu trúc để định dạng dòng bit dữ liệu: - Tập tin tiêu đ ề : a. Kiểu số nguyên: /* định nghĩa số nguyên không dấu 32 bit */ typedef unsigned int uint32; /* định nghĩa số nguyên không dấu 16 bit */ typedef unsigned short uint16; b. Con trỏ hàm (*BitsFcnPtr): Đây là m ột nguyên m ẫu hàm con trỏ cần phải có để ghi các bit vào dòng dữ liệu. Nó ghi “length” bits từ “value” bits, theo cách ghi msb-first. Các bit trong value giả định là right-justified. typedef void (*BitsFcnPtr)( uint32 value, uint16 length );
- c. Cấu trúc BF_BitstreamElement: Một BitstreamElement chứa đựng dữ liệu đã mã hoá sẽ được ghi vào dòng bit. “length” bit trong số “value” sẽ được ghi vào dòng bit theo msb-first. typedef struct { u int32 value; uint16 length; } BF_BitstreamElement; d. Cấu trúc BF_BitstreamPart: Một BitstreamPart bao gồm một nhóm các “nrEntries” của BitstreamElements. Mỗi BitstreamElement sẽ được ghi vào dòng bit theo thứ tự mà nó xuất hiện trong d ãy 'element'. typedef struct { u int32 nrEntries; BF_BitstreamElement *element; } BF_BitstreamPart; e. Cấu trúc BF_FrameData Cấu trúc này chứa đựng tất cả những thông tin cần thiết cho bộ định dạng dòng bit để m ã hoá một frame dữ liệu. Ta phải điền đầy nó và trỏ tới khi định dạng. typedef struct BF_FrameData { BitsFcnPtr putbits; /* your low-level bitstream function */ int frameLength; int nGranules;
- int nChannels; BF_BitstreamPart *header; BF_BitstreamPart *frameSI; BF_BitstreamPart *channelSI[MAX_CHANNELS]; BF_BitstreamPart *spectrumSI[MAX_GRANULES][MAX_CHANNELS]; BF_BitstreamPart *scaleFactors[MAX_GRANULES][MAX_CHANNELS]; BF_BitstreamPart *codedData[MAX_GRANULES][MAX_CHANNELS]; BF_BitstreamPart *userSpectrum[MAX_GRANULES][MAX_CHANNELS]; BF_BitstreamPart *userFrameData; } BF_FrameData; f. Các cấu trúc liên quan d ến bộ định dạng: Cấu trúc này chứa đựng thông tin được cung cấp bởi bộ định dạng dòng bit. Ta có thể sử dụng nó để kiểm tra và xem thử bộ m ã của ta có chấp nhận các kết quả của việc gọi bộ định dạng hay không. typedef struct BF_FrameResults { int SILength; int mainDataLength; int nextBackPtr; } BF_FrameResults; typedef struct BF_PartHolder { int max_elements; BF_BitstreamPart *part; } BF_PartHolder; typedef struct
- { int frameLength; int SILength; int nGranules; int nChannels; BF_PartHolder *headerPH; BF_PartHolder *frameSIPH; BF_PartHolder *channelSIPH[MAX_CHANNELS]; BF_PartHolder *spectrumSIPH[MAX_GRANULES][MAX_CHANNELS]; } MYSideInfo; 4. Cấu trúc huffcodetab: - Tập tin tiêu đ ề : - Sử dụng : dùng trong quá trình mã hoá dữ liệu theo thuật toán Huffman. struct huffcodetab { unsigned int xlen; /*max. x-index+ */ unsigned int ylen; /*max. y-index+ */ unsigned int linbits; /*number of linbits */ unsigned int linmax; /*max number to be stored in linbits */ HUFFBITS *table; /*pointer to array[xlen][ylen] */ unsigned char *hlen; /*pointer to array[xlen][ylen] */ }; 5. Các cấu trúc tính MDCT. - Tập tin tiêu đ ề : - Sử dụng : trong tính toán MDCT, định dạng dòng bit, tính toán mô hình tâm lý, mã hoá dữ liệu..
- typedef struct { unsigned part2_3_length; unsigned big_values; unsigned count1; unsigned global_gain; unsigned scalefac_compress; unsigned window_switching_flag; unsigned block_type; unsigned mixed_block_flag; unsigned table_select[3]; int /* unsigned */ subblock_gain[3]; unsigned region0_count; unsigned region1_count; unsigned preflag; unsigned scalefac_scale; unsigned count1table_select; unsigned part2_length; unsigned sfb_lmax; unsigned sfb_smax; unsigned address1; unsigned address2; unsigned address3; double quantizerStepSize; /* added for LSF */
- unsigned *sfb_partition_table; unsigned slen[4]; } gr_info; typedef struct { int main_data_begin; /* unsigned -> int */ unsigned private_bits; int resvDrain; unsigned scfsi[2][4]; struct { struct { gr_info tt; } ch[2]; } gr[2]; } L3_side_info_t; typedef struct { double l[2][2][21]; double s[2][2][12][3]; } L3_psy_ratio_t; typedef struct { double l[2][2][21]; double s[2][2][12][3]; } L3_psy_xmin_t; typedef struct { int l[2][2][22]; /* [cb] */
- int s[2][2][13][3]; /* [window][cb] */ } L3_scalefac_t; 6. Cấu trúc scalefac_struct: - Tập tin tiêu đ ề : struct scalefac_struct { int l[23]; int s[14]; }; B. Các định nghĩa. 1. Các định nghĩa dùng trong truy xuất dòng bit dữ liệu: - Tập tin tiêu đ ề : #define MINIMUM 4 /* Minimum size of the buffer in bytes */ #define MAX_LENGTH 32 /* Maximum length of word written or read from bit stream */ #d efine READ_MODE 0 #define WRITE_MODE 1 #define ALIGNING 8 #define BINARY 0 #define ASCII 1 #define TRUE 1 #define FALSE 0 #ifndef BS_FORMAT
ADSENSE
CÓ THỂ BẠN MUỐN DOWNLOAD
Thêm tài liệu vào bộ sưu tập có sẵn:
Báo xấu
LAVA
AANETWORK
TRỢ GIÚP
HỖ TRỢ KHÁCH HÀNG
Chịu trách nhiệm nội dung:
Nguyễn Công Hà - Giám đốc Công ty TNHH TÀI LIỆU TRỰC TUYẾN VI NA
LIÊN HỆ
Địa chỉ: P402, 54A Nơ Trang Long, Phường 14, Q.Bình Thạnh, TP.HCM
Hotline: 093 303 0098
Email: support@tailieu.vn