Làm việc với JMF

Time-Based Media:

Mọi dữ liệu có ý nghĩa thay đổi theo thời gian đều có thể được mô tả như là media data theo thời gian: Các đoạn âm thanh, hình ảnh, trình tự MIDI, hình ảnh động và các phương thức truyền thông đa phương tiện phổ biến hiện nay. Các loại dữ liệu truyền thong đa phương tiện nhu vậy có thể có được từ nhiều nguồn khác nhau, chẳng hạn như: có thể có sẵn trong máy của bạn, hay trên Internet, thu được từ camera, microphone, từ các chương trình phát song trên TV hay radio.

ở phần này, mô tả các đặc điểm chính của media data dựa trên thời gian và việc mô tả này có thể được khái quát qua sơ đồ sau:

·         Thu từ thiết bị ngoại vi.

·         Đọc từ file.

·         Nhận từ mạng(net).

 

 

·         Tạo bộ lọc.

·         Nén và giải nén.

·         Chuyển đổi định dạng.

 

 

·         Mô tả.

·         Lưu trữ.

·         Gửi vào mạng.

 

 

Mô hình xử lý truyền thông.

Streaming Media(media data theo luồng):

Một đặc tính quan trọng của truyền thông đa phương tiện dựa trên thời gian đó là đòi hỏi phải được cung cấp và xử lý. Khi một luồng media data bắt đầu, nó đòi hỏi một sự quản lý nghiêm ngặt về thời gian, và điều này phải được đáp ứng. Vì lý do này, media data dựa trên thời gian thường được gọi media data theo luồng(streaming media), điều này có nghĩa là nó được chuyển giao trên một luồng cụ thể và phải được tiếp nhận, xử lý trong một khung thời gian cụ thể và kết quả có thể chấp nhận được.

Ví dụ: khi một bộ phim được phát, nếu media data không được gửi một các nhanh chóng và đầy đủ thì sẻ xảy ra hiện tượng đứng và giật hình, thậm chí có thể bị phát lại. Mặt khác, nếu dữ liệu không được nhận và xử lý đủ nhanh, bộ phim có thể xuất hiện những đoạn hay khung hình bị bỏ mất, trong khi tốc độ trình chiếu vẫn bình thường.

Content type(kiểu nội dung):

Các media data được lưu thành các loại định dạng khác nhau, gọi là kiểu nội dung. Ví dụ: QuickTime, MPEG, WAV…. Về cơ bản, kiểu nội dung là kiểu của tập tin. Kiểu nội dung được định nghĩa bởi vì, các media data thường được thu thập từ nhiều nguồn khác nhau, hơn là thu được từ các tập tin địa phương(trên máy của bạn).

Media Streams(luồng media data):

Một luồng media data là các media data thu được từ các tập tin địa phương, qua mạng, hay có được từ các thiết bị ngoại vi như microphone, máy ảnh… Luồng media data thường các chứa nhiều kênh khác nhau của dữ liệu mà người ta gọi là các track. Ví du: một tập tin QuickTime có thể chứa cùng lúc cả kênh hình ảnh(video track) và kênh âm thanh(audio track).

Ghép kênh(multiplexing) là ghép nhiều kênh khác nhau(các kênh này có thể ở nhiều luồng khác nhau), thành một luồng duy nhất có chứa các kênh đó.

Phân rã kênh(demultiplexing) là quá trình phân rã một luồng có chứa kênh khác nhau thành các kênh riêng rẻ.

Một loại kênh có thể được nhận diện bằng loại dữ liệu mà nó chứa. Định dạng của một kênh định nghĩa cấu trúc mà kênh đó có.

Một luồng media data có thể được xác định vị trí và giao thức sử dụng để truy cập nó. Ví dụ: một URL, có thể được sử dụng để mô tả vị trí của một tập tin QuickTime trên một hệ thống địa phương hay một hệ thống từ xa. Nếu là tập tin địa phương, nó có thể được truy cập qua giao thức FILE(FILE protocol). Mặt khác, nếu là tập tin trên một máy chủ Web, tập tin có thể được truy cập qua giao thức HTTP. Một định vị địa phương cho media data(media locator) có thể cung cấp một cách khác để xác định vị trí của một luồng media data, khi URL không được sử dụng.

Các luồng media data có thể được phân loại dựa trên phương thức phân phối như sau:

Pull(kéo)- việc truyền dữ liệu được kiểm soát từ phía Client. Ví dụ: Hypertext Transfer Protocol(HTTP) và FILE là các giao thức pull.

Push(đẩy)- máy chủ bắt đầu việc truyề dữ liệu và kiểm soát các luồng dữ liệu. Ví dụ: giao thức truyền tải thời gian thực(RTP) là một giao thức dạng push, được sử dụng cho các luồng media data. Tương tự như vậy, giao thức SGI MediaBase cũng là giao thức dạng push, được sử dụng để truyền tải video theo yêu cầu.

Các định dạng media data phổ biến:

Các bảng sau đây cung cấp một số định dạng cho media data phổ biến hiện nay. Khi lựa chọn một định dạng, điều quan trọng là phải dựa vào các đặc điểm của nhận dạng của định dạng, môi trường mục tiêu và kết quả mong đợi thu được trên từng đối tượng cụ thể. Ví dụ: nếu bạn cần cung cấp các media data cho một trang Web, bạn cần cân nhắc đến các đặc điểm về băng thông.

Cột CPU là yêu cầu đặc trưng cho sức mạnh xử lý cần thiết để kết xuất một các tốt ưu nhất cho một định dạng. Cột băng thông là yêu cầu đặc trưng cho tốc độ đường truyền dẫn cần thiết để gửi hoặc nhận một cách nhanh chóng để kết xuất tối ưu.

Định dạng Kiểu nội dung Chất lượng CPU yêu cầu Băng thông yêu cầu
Cinepak AVI

QuickTime

Trung bình Thấp Cao
MPEG-1 MPEG Cao Cao Cao
H.261 AVI

RTP

Thấp Trung bình Trung bình
H.263 QuickTime

AVI

RTP

Trung bình Trung bình Thấp
JPEG QuickTime

AVI

RTP

Cao Cao Cao
Indeo QuickTime Trung bình Trung bình Trung bình

Một số định dạng video phổ biến.

Định dạng Kiểu nội dung Chất lượng CPU yêu cầu Băng thông yêu cầu
PCM AVI

QuickTime

WAV

Cao Thấp Cao
Mu-Law AVI

QuickTime

WAV

RTP

Thấp Thấp Cao
ADPCM(DVI,IMA4) AVI

QuickTime

WAV

RTP

Trung bình Trung bình Trung bình
MPEG-1 MPEG Cao Cao Cao
MPEGLayer3 MPEG Cao Cao Trung bình
GSM WAV

RTP

Thấp Thấp Thấp
G.732.1 WAV

RTP

Trung bình Trung bình Thấp

Một số định dạng âm thanh phổ biến.

Trình diễn media data (Media presentation):

Hầu hết media data là dữ liệu âm thanh hay hình ảnh, chúng có thể được trình diễn thông qua các thiết đầu ra như loa và màn hình. Những thiết bị như vậy là điểm đến của hầu hết các media data. Các luồng dữ liệu có thể được gửi tới được bất cứ đâu, ví dụ: được lưu thành các tập tin hay được truyền đi trên mạng. Một đầu ra cho media data đôi khi còn được gọi là “bể dữ liệu”(data sink).

Kiểm soát trình diễn(Presentation Controls)

Trong khi một luồng media data đang được trình diễn, VCR- một cách kiểm soát kiểm soát trình diễn có thể được cung cấp cho người dung để có thể kiểm soát các thao tác này. Ví dụ: một bảng điều khiển có thể được cung cấp trong các chương trình chơi nhạc hay xem phim, chúng cho phép người dùng dừng, bắt đầu hay phát lại, chuyển tiếp hay tua các đoạn media data đa được trình diễn.

Độ trễ(Latency)

Trong nhiều trường hợp, đặc biệt là khi luồng media data đang cư trú trên mạng, việc trình diễn các luồng dữ liệu này không thể được bắt đầu ngay lập tức. Thời gian trước khi dữ liệu được trình diễn gọi là độ trễ bắt đầu(the start latency). Người dùng có thể cảm nhận được điều này, đó là sự chậm trễ từ khi họ ra lệnh bắt đầu cho tới khi dữ liệu thực sự được trình diễn.

Trình diễn media data thường kết hợp media data vào một số phép đồng bộ. Ví dụ: nhạc nền có thể được phát trong khi chạy một ứng dụng trình chiếu ảnh, một đoạn âm thanh có thể được lồng ghép trong một đoạn video. Khi trình diễn một luồng media data đã được đồng bộ, điều quan trọng là quản lý được độ trễ bắt đầu của các luồng con bên trong, nếu không sự bắt đầu của các dòng các nhau sẽ được bắt đầu tại các thời điểm khac nhau.

Chất lượng trình diễn(Presentation quality)

Chất lượng trình diễn một luồng media data phụ thuộc vào nhiều yếu tố, bao gồm

Mô hình nén được sử dụng.

Khả năng xử lý của hệ thống phát.

Băng thông sẵn có(cho các luồng media data qua mạng).

Thông thường, tập tin có chất lượng cao hơn và kích thước lớn hơn thường có quyền lớn hơn trong việc yêu cầu và chiếm giữ băng thông phục vụ cho việc xử lý. Băng thông thường được biểu diễn như là số bit truyền được trong một khoảng thời gian nhất định, còn được gọi là bit rate.

Để đạt được sự trình diễn video chất lượng cao, đòi hỏi số khung hình trong từng đơn vị thời gian(frame rate) càng cao càng tốt. Thông thường, một bộ phim đạt được 30khung hình trên mỗi giây được coi là khó phân biệt(giữa các khung hình): chương trình TV hay băng hình.

Xử lý media data:

Trong hầu hết các trường hợp, dữ liệu của một luồng media data sẽ được xử lý trước khi chúng được trình diễn cho người dùng. Một số hoạt động xử lý có thể liệt kê như sau:

Nếu là luồng ghép, các kênh đơn sẽ được tách ra.

Nếu là một kênh đơn được nén, nó sẽ được giải mã.

Nếu cần thiết, các kênh có thể được chuyển đổi thành những định dạng khác nhau.

Bộ lọc hiệu ứng có thể được áp dụng để giải mã các kênh(nếu cần).

Sau đó, các kênh này sẽ được chuyển giao cho các thiết bị đầu ra thích hợp. Nếu các luồng media data phải được lưu trữ thay vì được đưa đến các thiết bị đầu ra, các giai đoạn này có thể bị thay đổi một chút. Ví dụ: nếu bạn muốn thu lấy hình ảnh và âm thanh từ máy quay, xử lý chúng và lưu trữ vào một tập tin, thì các giai đoạn có thể như sau:

Các kênh hình ảnh và kênh âm thanh sẽ được thu lấy.

Bộ lọc hiệu ứng có thể được áp dụng nếu bạn muốn thu được các kênh nguyên chất.

Các kênh riêng biệt sẽ được mã hóa.

Các kênh sẽ được ghép và nén vào một luồng media data duy nhất.

Luồng media data sẽ được lưu thành một tập tin

Tách kênh(demultipexers) và ghép kênh(multiplexers):

Tách kênh là chiết xuất để thu được các kênh riêng biệt từ một luồng media data ghép. Ghép kênh là thực hiện chức năng ngược lại, lấy các kênh riêng biệt và thực hiện ghép chúng vào một luồng media data duy nhất, luồng này gọi là luồng media data ghép.

Các bộ codec:

Một codec thực hiện nén và giải nén media data. Khi một kênh được mã hóa, nó được chuyển đổi sang một định dạng thích hợp cho việc lưu trữ hay truyền tải, khi nó được giả mã, nó được chuyển đổi thành một định dạng(thô) không nén phù hợp.

Mỗi codec đều có định dạng đầu vào, và chắc chắn rằng nó có thể xử lý được và đảm bảo rằng định dạng đầu ra là khả thi. Trong một số trường hợp, một loạt các codec có thể được sử dụng việc chuyển đổi định dạng.

Bộ lọc hiệu ứng:

Một bộ tạo hiệu ứng có thể thay đổi kênh dữ liệu theo một kiểu nào đó, chúng thường xuyên được sử dụng để tạo ra các hiệu ứng đặc biệt.

Bộ lọc hiệu ứng có thể được phân loại được dựa trên loại hình chúng được áp dụng: tiền xử lý hay kết quả kết xuất có được. Thông thường, bộ lọc tín hiệu được áp dụng cho các dữ liệu đang còn ở dạng thô.

Bộ kết xuất(renderers):

Một kết xuất là một khái niệm trừu tượng đại diện chi một thiết bị trình diễn. Đối với âm thanh, thông thường, thiết bị âm thanh là card âm thanh của máy tính mà kết quả sẽ được xuất ở đầu ra là loa. Đối với video, thiết bị trình diễn là màn hình máy tính.

Ghép(composting):

Hiện nay, có một số thiết bị chuyên dụng hỗ trỡ việc ghép. Việc ghép trên một media data là quá trình kết hợp nhiều kênh của dữ liệu vào một phương tiện trình diễn duy nhất. Ví dụ: phủ một bản lên một đoan video là một hình thức phổ biến. Ghép  có thể thực hiện trên phần cứng hay phần mềm. Một thiết bị thực hiện ghéo có thể được như bộ kết xuất nhiều kênh đầu vào.

Thu (Media capture):

Media data theo thời gian có thể được “chụp” lại từ một nguồn thực, sau đó được xử lý và trình diễn lại. Ví dụ: âm thanh có thể được thu từ một microphone hoặc một đoạn video có thể thu được từ một máy ảnh. Chúng có thể được coi là đầu vào của một mô hình xử lý xử lý truyền thông tiêu chuẩn.

Một thiết bị thu có thể cung cấp nhiều luồng media data. Ví dụ: một máy quay video có thể cung cấp cả hình ảnh và âm thanh. Những luồng này có thể được thu lấy một cách riêng biệt hoặc kết hợp thành một luồng duy nhất có chứa cả kênh âm thanh và kênh hình ảnh.

Thiết bị thu(Capture devices):

Để “bắt” được các media data theo thời gian, chúng ta cần có phần cứng chuyên dụng, ví dụ: để thu được âm thanh bạn cần một microphone và một card âm thanh. Tương tự như vậy, để thu một chương trình truyền hình bạn cần một TV và một card đồ họa. Hầu hết các hệ thống cung cấp một cơ chế truy vấn để tìm ra được những thiết bị có sẵn trong máy tính của bạn.

Các thiết bị thu có thể được mô tả như một trong hai loại nguồn pull hay nguồn plus. Ví dụ: máy ảnh là một nguồn pull, nguồn sử dụng có thể kiểm soát khi chụp hình ảnh. Trong khi đó, microphone là nguồn plus, chúng lien tục cung cấp dữ liệu âm thanh từ các môi trường xung quanh mà người dùng không thể kiểm soát việc thu này.

Các định dạng của một luồng media data thu được từ một thiết bị bị thuộc vào khả năng xử lý của thiết bị đó. Một số thiết bị xử lý được rất ít các định dạng. Bên cạnh đó, cũng có thiết bị xử lý được rất nhiểu định dạng khác nhau.

Kiểm soát thu(capture controls):

Đôi khi, bộ kiểm soát có thể cung cấp cho người dùng nhiều chức năng quản lý quá trình thu. Ví dụ: một bảng điều khiển có thể cho phép người dùng xác định tốc  độ thu, loại mã hóa cho dữ liệu, cũng như các chức năng cho phép bắt đầu và ngừng việc thu dữ liệu.

JMF

Java Media Framework(JMF) cung cấp một kiến trúc thống nhất và giao thức truyền tin để quản lý việc thu nhận, cung cấp và xử lý media data theo thời gian. JMF được thiết kế để hỗ trợ nhiều tiêu chuẩn định dạng như: AIFF, AU, AVI, GSM, MIDI, MPEG, QuickTime,RMF, và WAV.

Bằng cách khai thác các lợi thế của nền tảng Java, JMF mang đến một khẩu hiệu “Write once, run anywhere” – (viết chỉ một lần, và chạy được bất cứ đâu) để phát triển những ứng dụng truyền thông đa phương tiện như âm thanh và video. JMF cung cấp các hàm Java API cơ bản, từ đó, cho phép người lập trình can thiệp sâu hơn vào các media framework. JMF có khả năng thúc đẩy việc triển khai cho những hệ thống căn bản nhất, bên cạnh đó, người lập trình có thể dễ dàng tạo ra những chương trình ứng dụng có tính năng động cao với JMF API.

Với JMF, bạn có thể dễ dàng tạo ra các chương trình ứng dụng hay các applet như trình diễn, thu thập và lưu trữ media data. Framework này cho phép các nhà phát triển và các nhà cung cấp ứng dụng thực hiện các chương trình truyền thông đa phương tiện với dữ liệu thô và có thể mở rộng hay bổ sung thêm có định dạng mới, kiểu nội dụng mới, và tạo ra có cơ chế trình diễn mới.

Kiến trúc

Các thiết bị như băng từ và VCR cung cấp một mô hình quen thuộc để thu thập , lưu trữ, xử lý và trình diễn media data dựa trên thời gian. Khi bạn xem phim bằng VCR, khi bạn cho vào một cuộn băng từ, đồng nghĩa với việc bạn bạn đã cung cấp một nguồn madia data. VCR đọc và giải mã dữ liệu, gửi các tín hiệu thích hợp tới màn hình và loa.

Mô hình xử lý bằng VCR.

JMF sử dụng cùng một mô hình tương tự như trên. Một nguồn dữ liệu(data source) được đóng gói đóng vai trò như một cuộn băng từ và một bộ phát(player) để xử lý và kiểm soát tương tự như một VCR. Để JMF có thể thực hiện tốt vai trò này, nó yêu cầu dữ liệu đầu vào và đầu ra thích hợp.

Nguồn dữ liệu và bộ phát là hai bộ phận không thể thiếu trong mô hình của kiến trúc của JMF API, điều này chắc rằng việc thu nạp, trình diễn, và xử lý media sẽ được sẽ lý. Bên cạnh đó, JMF cũng hỗ trợ những hàm API cấp thấp hơn, thích hợp cho việc tùy chỉnh các chức năng xử lý và mở rộng chúng. Chúng cung cấp cho nhà phát triển trên nền tảng Java những hàm API đơn giản và dễ sử dụng  để có thể tích hợp các chức năng xử lý media data vào ứng dụng mà minh xây dựng, duy trì cho các ứng dụng sự năng động và khả năng tương thích tốt, cho chúng khả năng có thể được mở rộng khi cần thiết, là nền tảng để xây dựng các ứng dụng truyền thông đa phương tiện tiên tiến, sở hữu những công nghệ tương lai.

Mộ hình kến trúc của JMF

Mộ hình thời gian(Time model):

Các ứng dụng viết bằng JMF có độ chính xác tính bằng đến từng nano giây. Các đặc điểm về thời gian sẽ được mô tả trong JMF, đại diện cho điều này là đối tượng Time, đã được xây dựng sẵn trong JMF. Đặc điểm kỹ thuật vượt trội của class này là có khả năng hỗ trợ độ chính xác đển nano giây.

Một class khác trong JMF đóng vai trò đồng bộ, đó là Clock. Clock thực hiện nhiệm vụ như một cái đồng hồ, dùng để theo dõi thời gian cho một luồng media data thực. Clock cung cấp một giao diện linh hoạt và cơ bản để thực hiện việc đồng bộ và kiểm soát quá trình của một luồng media data.

Mô hình thời gian trong JMF

Một Clock “sở hữu” một TimeBase để theo thời gian  của một luồng media data đang được xử lý. Một Time-Base cung cấp các mốc thời gian liên tục đến từng tic-tắc. Một điều quan trọng là, TimeBase chỉ cung cấp thời gian hiện tại mà nó đang nắm giữa, gọi là thời gian cơ sở(time-base). Thời gian cơ sở này không thể bị dừng lại cũng như cũng không được phép thiết lập từ người dùng. Thời gian cơ sở là thời gian được dựa trên thời gian hiện tại của đồng hồ hệ thống.

Đối tượng Clock trong JMF đại diện cho vị trí hiện tại bên trong một luồng media data- bắt đầu của một luồng media data là mốc 0, và mốc kết thúc là thời gian tối đa để xử lý luồng đó. Duration (khoảng thời gian) của một luồng media data được tính từ lúc bắt đầu cho tới khi kết thúc-là thời gian cần thiết để trình diễn xong luồng media data đó(các đối tượng có thể cung cấp thông tin Duration khi chúng có thể nhận biết được Duration của mình).

Để theo dõi một kênh media data , một Clock sử dụng:

Time-Base Start-Time: mốc thời gian mà Time-Base nhận được yêu cầu trình diễn.

Media Start-Time: mốc thời gian mà luồng media data thực sự được trình diễn.

Playback rate: tốc độ trình diễn, nó cho thấy Clock chạy nhanh ra sao, được thể hiện trong mối tương quan quan vói Time-Base. Ví dụ: ta có tốc độ phát rate=1.0, cho thấy tốc độ trình diễn bình thường, với rate=2.0, chỉ ra rằng luồng media data đang được trình diễn với tốc độ gấp đôi tốc độ bình thường. Một rate<0 cho thấy rằng Clock đang chạy ngược lại với Time-Base của chính nó. Điển hình cho điều này là khi ta phát ngược lại một luồng media data.

Khi bắt đầu một luồng media data được bắt đầu trình diễn, Media-Time  sẽ được ánh xạ thành một Time-Base, và sự thay đổi(tiếp tục) của Time-Base này sẽ được dùng để tính toán thời gian đã thực hiện trình diễn. Trong suốt quá trình trình diễn của luồng media data, Media-Time hiện tại sẽ được tính theo công thức:

MediaTime=MediaStartTime+rate*(TimeBaseTime-TimeBaseStartTime)

Khi quá trình dừng, Media-Time dừng, nhưng Time-Base vẫn tiếp tục được tính. Nếu quá trình trình diễn được khởi động lại, Media-Time sẽ được tính lại như khi một luồng media data được trình diễn.

Quản lý(Manager)

JMF API chủ yếu chứa các hàm định nghĩa hành vi và sự tương tác của các đối tượng thu nhận, xử lý, và xử lý theo Time-Base. Các hàm này đã được cung cấp sẵn trong framework này. Bằng cách sử dụng một class trung gian được gọi là managers, JMF làm cho việc triển khai các nó trở nên dễ dàng hơn.

JMF cung cấp bốn loại managers:

Manager: quản lý các hàm khởi tạo cho cái đối tượng Player(bộ trình diễn), Processcer(bộ xử lý), DataSource(nguồn dữ liệu), DataSick(“bể” chứa dữ liệu). Đây là cấp độ trung gian để có thể giao tiếp với JMF. Nhìn chung, các đối tượng này có cùng một cách khởi tạo dù cho mỗi loại có thể yêu cầu một vài tùy chỉnh riêng biệt.

PackageManager: đóng vai trò như một “sổ đăng ký” cho cái đối tượng Player, Processer, DataSource, DataSick.

CaptureDiviceManager: thực hiện đăng ký cho các thiết bị thu có sẵn.

PlugInManager: thực hiện việc đang ký cho các thành phần như: Multiplexer, Demultiplexer, Codec, Effect, Renderer.

Để xây dựng một ứng dụng dựa trên JMF, điều trước tiên là bạn phải tạo ra một Manager để quản lý các phương thức khởi tạo cho Player, Processcer, DataSource, và DataSink.  Nếu muốn có được dữ liệu từ các thiết bị thu ngoại vi, bạn có thể sử dụng phương thức CaptureDeviceManager để tìm ra xem những thiết bị ban cần đang có thật sự kết nối và phương thức này cũng giúp cho phép truy cập vào những thiết bị này. Nếu bạn quan tấm đến việc sử lý dữ liệu từ các plug-in, JMF cung cấp cho ban phương thức PlugInManager để kiểm soát được dữ liệu từ các plug-in này.

Nếu bạn muốn tạo riêng cho mình một plug-in mới, bạn có thể kết thừa các chức năng được xây dựng sẵn của JMF thông qua PlugInManager để có được một Processer hỗ trợ các hàm API đã được xây dựng sẵn. Để có thể tùy chỉnh các chức năng của Player, Processer, DataSource, DataSink với JMF, bạn có thể kết thừa lớp PackageManager.

Mô hình sự kiện (Event Model):

JMF sử dụng một cơ chế quản lý sự kiện(Event) có cấu trúc, điều này giúp cho các ưng dụng được xây dựng bằng JMF có thể quản lý được hiện trạng của hệ thống truyền thông cũng như quản lý được các lỗi điều khiển như: lỗi dữ liệu, lỗi thiết bị đầu vào… Bất cứ khi nào, một đối tượng được xây dựng trên JMF muốn thông báo một sự kiện, nó sẽ gửi đi một MediaEvent. Để nhận được MediaEvent này, bạn cần đăng ký một “người tiếp nhận” thích hợp với đối tượng mà bạn muốn thu được MediaEvent của nó, bằng cách gọi phương thức Listener.

Các đối tượng điều kiển(chẳng hạn như Player hay Processcer) và một số đối tượng chứa các đối tượng điều khiển như GainControl là các đối tượng có thể gửi MediaEvent.

Mô hình quản lý sự kiện trong JMF.

RTPSessionManager cũng là đối tượng cung cấp các MediaEvent, sẽ tìm hiểu kỹ thêm ở những phần sau.

Mô hình dữ liệu (Data Model):

Các bộ trình diễn được xây dựng bằng JMF sử dụng sử dụng các DataSource để quản lý việc chuyển giao dữ liệu của các luồng media data. Một DataSource xác định cả vị trí nguồn, phương thức và phần mềm dùng để truyền luồng media data. Sau khi được sử dụng, một DataSource không thể được tái sử dụng để cung cấp cho một nguồn dữ liệu đa phương tiện khác.

Trong JMF, một DataSource được xác định bởi một MediaLocator hoặc bởi một URL(universal resource locator) được dùng để tham chiếu đến tài nguyên trên Internet. Một MediaLocator tương tự như một URL, và có thể được định nghĩa thông qua một URL, nhưng nó có thể được định nghĩa ngay cả khi các giao thức xử lý tương ứng không được cài đặt trên hệ thống(trong Java, một URL có thể được xử lý nếu giao thức xử lý tương ứng đã được cài đặt trên hệ thống).

Một DataSource quản lý một tập các đối tượng SourceStream. Một DataSource tiêu chuẩn được xây dựng như một mảng các byte(đơn vị truyền dữ liệu). Để truyể dữ liệu từ DataSource, bạn sử dụng mốt đối tượng khác là Buffer, Buffer thực hiện dữ liệu theo từng byte. Một số DataSource thông dụng trong JMF là:

Mô hình dữ liệu trong JMF.

Các nguồn dữ liệu Pull(Pull Data-Source) và nguồn dữ liệu Push(Push Data-Source):

Pull Data-Source: việc khởi tạo truyền dữ liệu và kiểm soát luồng media data được thực hiện từ phía client. Các giao thức truyền dữ liệu thuộc dạng này như: Hypertext Transfer Protocol(HTTP) và FILE. JMF định nghĩa hai loại nguồn dữ liệu Pull: PullDataSourcePullBufferData, trong đó PullBufferData sử dụng bộ đệm để thực hiện việc truyền dữ liệu.

Push Data-Source: việc khởi tạo truyền dữ liệu và kiểm soát luồng media data được hiện từ phía server. Các nguồn dữ liệu Push có thể được biết đến như: dữ liệu quảng bá qua vô tuyến, các dạng dữ liệu quảng bá trong các mạng, dịch vụ video theo yêu cầu(VOD –video on demand). Đối với các dữ liệu được phát qua vô tuyến, được áp dụng một giao thức truyền tải thời gian thực là RTP(Real-time Transport Protocol), được phát triển bởi IETF(Internet Engineering Task Force). Đối với các dịch vụ VOD, chúng được áp dụng một giao thức khác là MediaBase, được phát triển bởi SGI. JMF định nghĩa hai dạng nguồn dữ liệu Push: PushDataSourcePushBufferDataSource, trong đó PushBufferDataSource sử dụng một bộ đệm để thực hiện truyền dữ liệu.

Mức độ kiểm soát được hiểu là các chức năng kiểm soát mà các trình khách có thể cung cấp cho người dùng, việc này thùy thuộc vào từng loại nguồn dữ liệu được trình diễn. Ví dụ: một tập tin MPEG có thể được thay đổi vị trí lưu trữ, một trình khách có thể cho phép người dùng kiểm soát việc trình diễn một đoạn video. Ngược lại, các dữ liệu quảng bá được kiểm soát máy chủ và các trình khách không thể tác động vào các tập tin này. Một vài giao thức VOD có thể hỗ trợ người dùng một cách hạn chế: một trình khác có thể cho phép người dùng chọn vị trí trình diễn mới tùy thích , như lại xử lý không nhanh khi người dùng thực hiện tao tác tua(về trước hay về sau).

Các nguồn dữ liệu đặc biệt

JMF định nghĩa hai nguồn dữ liệu đặc biệt: nguồn dữ liệu khả nhân bản(cloneable data) và nguồn dữ liệu hợp nhất(merging data).

Nguồn dữ liệu nhân bản được sử dụng khi bạn muốn tạo một bản sao cho một nguồn dữ liệu Pull hay Push. Để tạo một bản sao: bạn cần gọi phương thức createCloneableDataSource từ một đối tượng dạng Manager, sau đó tham chiếu tới một DataSource mà bạn muốn nhân bản. Khi một nguồn dữ liệu được nhân bản bằng phương thức createCloneableDataSource, bạn chỉ nên tao thác với nguồn dữ liệu nhân bản và không nên thao tác trực tiếp lên nguồn dữ liệu chính.

Nguồn dữ liệu khả nhân bản là thể hiện(implements) của lớp đại diện SourceCloneable, trong đó, định nghĩa một phương thức duy nhất là createClone. Số lượng bản sao mà bạn có thể tạo được là tùy ý, tuy nhiên nguồn dữ liệu mà bạn muốn tạo bản sao phải là nguồn có khả năng nhân bản(cloneable datasource). Các bản sao cũng có các phương thức hoạt động tương tự như bản gốc: các phương thức kiểm soát connect(kết nối), disconnect(ngắt kết nối), start(bắt dầu), stop(dừng), và các phương thức truyền, phù hợp với từng loại dữ liệu.

Các bản sao không nhất thiết phải có các thuộc tính giống với bản gốc dùng để tạo ra chúng hay các bản sao khác. Ví dụ: một nguồn dữ liệu khả nhân bản được tạo ra cho một thiết bị thu(máy quay, máy ảnh…) có thể được xem như một nguồn “cha” cho tất cả các bản sao của nó, trong trường hợp này, các bản sao sẽ không được tạo ra, trừ khi bản gốc được sử dụng. Nếu bạn sử dụng một hay nhiều bản gốc và một hay nhiều bản sao tại cùng một thời điểm, thì các bản sao khác sẽ được tạo ra với số bản gốc được sử dụng.

Với nguồn dữ liệu kết hợp, bạn có thể kết hợp các SourceStream từ nhiều nguồn dữ liệu thành một nguồn dữ liệu duy nhất. Điều này cho phép một tập hợp các nguồn dữ liệu được kiểm soát từ một điểm duy nhất. Một khi các phương thức kiểm soát như connect, disconnect, start, stop  được gọi trong nguồn dữ liệu kết hợp, chúng sẽ được gửi đến từ nguồn dữ liệu thành phần.

Để xây dựng một nguồn dữ liệu kết hợp, bạn cần gọi tới phương thưc createMergingDataSource trong một đối tượng Manager, phương thức này sẽ tham chiếu tới một mảng bao gồm các DataSource. Để việc xác nhập được thực hiện, các nguồn dữ liệu phải có cùng kiểu nội dung, ví dụ: một nguồn dữ liệu dạng PullDataSource không thể kết hợp với một nguồn dữ liệu dạng PushDataSource. Độ lớn của nguồn dữ liệu kết hợp là tổng độ lớn tối đa của các nguồn dữ liệu thành phần.

Dịnh dạng dữ liệu

Định dạng của một dữ liệu đa phương tiện được định nghĩa thông qua một đối tượng định dạng là Format. Một định dạng mang trong mình các tham số mã hóa đặc trưng hay các thông tin định thời, tên của định dạng, và loại dữ liệu phù hợp.

JMF cung cấp các loại định dạng cụ thể như sau:

Các định dạng dữ liệu đa phương tiện trong JMF.

AudioFormat la định dạng âm thanh, nó bao gồm các mô tả như: tốc độ phát, số kênh và số bit/mẫu. VideoFormat là một gói định dạng cho video bao gồm:

IndexdColorFormat.

RGBFormat.

YUVFormat.

JPEGFormat.

H261Format.

H263Format.

Để nhận được cảnh báo khi định dạng bị thay đổi, bạn sử dụng một ControllerListener và “lắng nghe” sự kiện FormatChangeEvents(để biết thêm thông tin, bạn có thể tham khảo tại phần Phản ứng với các sự kiện truyền thông).

Điều kiển(Control):

JMF cung cấp một cơ chế điều kiển thông quan việc thiết lập và truy vấn các thuộc tính của đối tượng. Một đối tượng điều kiển thường cung cấp cho người dùng khả năng truy cập vào phần thông tin giao tiếp người dùng , từ đó cho phép người dùng kiểm soát đối tượng thông qua các thuộc tính của nó. JMF cung cấp nhiều loại đối tượng điều kiển như: Controller, các DataSource, các DataSink, và các plug-in.

Bất kỳ một lớp nào muốn cung cấp khả điều kiển đều phải là một thể hiện(implements) của lớp Controls và các lớp điều kiển khác tương ứng mà bạn muốn sử dụng. Các lớp điều kiển này cung cấp nhiều phương thức để bạn có thể truy cập và kiểm soát các đối tượng chứa chúng. Các DataSourcePlugIn sử dụng các lớp thể hiện điều kiển để hiện thực khả năng truy cập vào các thành phần điều kiển của chúng.

CachingControl cho phép theo dõi và hiển thị các trình tải về. Nếu có một nhu cầu tải về từ Player hay Processer, nó sẽ hiện thực quá trình tải này qua một thanh tiến trình(process bar) cho phép người dùng theo dõi một cách trực quan toàn bộ tiến trình tải.

GainControl cho phép điều chỉnh mức độ của các kênh âm thanh như thiết lập cũng như tắt âm lượng đầu ra của các đối tượng như Player hay Processer, nó cũng hỗ trợ cơ chế nhận biết những thay đổi về âm lượng.

GianControl

 

Control

Các đối tượng DataSink hoặc Multiplexer đọc luồng media data từ một DataSource và ghi nó đến đích cuối cùng bằng một lớp thể hiện của StreamWriterControl. Lớp điều kiển này cho phép người dùng giới hạn kích thuốc đầu ra của luồng media data.

FramePositioningControlFrameGrabbingControl: thực hiện việc chiết xuất khung hình(frame) tùy thuộc vào khả năng của PlayerProcesser. FramePositioningControl cho phép xác định chính xác một frame trong một luồng media data đang “chảy ” qua một Player hay một Processer. FrameGrabbingControl cung cấp khả năng lấy ra một frame từ một luồng media data hiện hành. FrameGrabbingControl cũng hỗ trợ các kết xuất(Renderer) ở các mức độ khác nhau.

Các đối tượng có chứa thuộc tính dạng Format có hiện thực lớp FormatControl để cho phép truy cập đến thuộc tính này. FormatControl cũng cung cấp các chắc năng truy vấn và thiết lập cho các Format.

TrackControl cũng là một dạng của FormatControl, tuy nhiên nó cung cấp các chức năng kiểm soát hiệu suất của một Processer đang thực hiện xử lý một luồng media data. Với TrackControl, bạn cũng có thể thực hiện chuyển đổi các định dạng được thực hiện trên từng kênh đơn và tùy chọn Effect(hiệu ứng), Codec, hoặc Renderer được xử dụng trong Processer. (có thể tham khảm thêm tại phần Tùy biến xử lý với JMF).

Hai đối tượng điều kiển khác là PortControlMonitorControl cung cấp cho người dùng khả năng kiểm soát quá trình thu dữ liệu. PortControl xác định phương thức đầu ra của các thiết bị thu. MonitorControl cung cấp khả năng duyệt trước nguồn dữ liệu từ các thiết bị thu hay khi chúng được mã hóa.

BufferControl cho phép người dùng kiểm soát các vùng đệm khi thực thi một đối tượng cụ thể.

JMF cũng cung cấp một vài đối tượng điều kiển để kiểm soát quá trình mã hóa và giải mã bằng phần cứng hay phần mềm:

BitRateControl: cung cấp khả năng kiểm soát tốc độ dữ liệu đầu vào hoặc kiểm soát tốc độ mã hóa. Cho phép kiểm soát tới mức bit/s.

FrameProcessingControl: cung cấp các thông số kỹ thuật đặc trưng của một frame, cho phép thao tác cùng với bộ Codec ở mức tối thiểu nhất.

FrameRateControl:cho phép thay đổi tốc độ duyệt frame.

H261Control: cho phép kiểm soát các thông số mã hóa cho luồng video H.261 ở chế truyển tải hình ảnh.

H263Control: cho phép kiểm soát luồng video mã hóa theo chuẩn H.263, bao gồm: vector vô hướng, mã hóa số học có cú pháp(arithmetic coding– chũ yếu sử dụng cho việc nén dữ liệu chất lượng cao), cơ chế dự đoán nâng cao khi thực hiện tua về trước hay về sau gọi là P-Bframe, và phần quản lý các lỗi mỡ rộng.

KeyFrameControl: cho phép quản lý các đặc trưng của các frame chính. Các bộ mã hóa có thể thực hiện ghi đè lên frame chinh nếu cần thiết.

MpegAudioCotrol: cung cấp khả năng chiết xuất một tập tin MPEG và kiểm soát các tham số mã hóa của tập tin này.

QualityControl: cung cấp các mô tả chất lượng đi kèm với từng định dạng và khả năng kiểm soát CPU khi sử dụng bộ mã hóa. Điều này cho thấy, có thể đạt được những mức chất lượng khác tùy thuộc vào các hiệu ứng và loại hình nén được sử dụng. Việc thiết lập chất lượng đầu ra cao hơn có thể thu được kết quả có chất lượng tốt hơn, ví dụ: chất lượng hình ảnh tốt hơn cho các đoạn video.

SilenceSuppressionControl: cho phép kiểm soát các đặc điểm của các tham số chủ yếu của ức chế sự tĩnh lặng(Silence suppresion) của một Codec. Khi chế độ ức sự chế tĩnh lặng được bật, bộ giả mã sẽ không kết xuất ra bất cứ dữ liệu nào nếu nó nhận được cảnh báo bắt đầu một đoạn ức chế sự tĩnh lặng.

Các công cụ giao tiếp với người dùng:

Một Control có thể cung cấp khả năng giao tiếp với người dùng đầu cuối và khả năng kiểm soát hành vi của họ. Để có được một thể hiện Component mặc định của Control hiện tại, bạn gọi tới phương thức getControlComponent. Phương thức này trả về một đối tượng AWT mà bạn có thể thêm vào ứng dụng của mình.

Một Controller cũng có thể cho phép truy cập đến các thuộc tính dạng Component được định nghĩa bên trong chúng. Ví dụ: một đối tượng Player cung cấp khả năng truy cập đến cung cụ giao tiếp bên trong thông qua phương thức getVisualComponentgetControlPanelComponent.

Nếu bạn không muốn sử dụng các Component đã được định nghĩa sẵn, bạn cũng có thể hiện thực riêng cho mình một công cụ riêng để thực hiện những tác vụ tương tác với người dùng tùy thích. Ví dụ: bạn có thể hiện thực một công cụ giao tiếp với người dùng cho một Player. Các hoạt động giao tiếp trên giao diện sẽ được các thành thích hợp khác chuyển giao cho Player bên dưới, chẳng hạn như các phương thức start hoặc stop. Bằng cách đăng ký các đối tượng kiểm soát có vai trò “lắng nghe” như các đối tượng ControllerListener cho một Player, bạn có thể cung cấp khả năng phản ứng thích hợp với người dùng(thông qua giao diện) đến với Player.

Khả năng mở rộng:

Chúng ta có thể mở rộng JMF bằng 2 cách:

Bẳng cách hiện thực các công cụ(plug-in) tùy ý, chúng ta có thể kế thừa những thành phần tiêu chuẩn đã được xây dựng sẵn để tạo ra một công cụ cho riêng mình.

Hiện thực một cách trực tiếp các đối tượng như Controller, Player, Processer, DataSource, hoặc DataSink.

Khi hiện thực một plug-in, ban có thể tùy chỉnh hay mở rộng thêm các tính năng của một Processer mà không phải bắt tay xây dựng từ đầu. Sau khi một plug-in được đăng ký với JMF, nó có thể được lựa chọn như một quá trình xử lý tùy chọn, miễn là nó được xây dựng bằng API trong Java. Trong Java, plug-in có thể được sử dụng:

Bạn có thể thay thế hay mở rộng một Processer hoạt động độc lập bằng plug-in của mình.

Truy cập vào luồng media data “đang chảy” tại các điểm cụ thể. Ví dụ: bạn có thể sử dụng các plug-in hiệu ứng tại đầu vào và đầu ra của một Processer để tạo hiệu ứng cho luồng media data hiện hành.

Xử lý dữ liệu bên ngoài ProcesserPlayer. Ví dụ: bạn có thể dùng một plug-in tách kênh để xử lý cho một luồng media data ghép, do đó bạn có thể chơi các bản nhạc thông qua Sound(âm thanh) trong Java.

Trong tình huống, người lập trình muốn có được sự linh động và xử lý tốt hơn cho các đối tượng Controller, Player, Processer, DataSource, DataSink, thể hiện của các đối tượng này có thể được thay đổi hay mở rộng để đáp ứng với từng nhu cầu. Ví dụ: nếu bạn muốn có một bộ giải mã MPEG trên phần cứng, bạn có thể hiện thực một Player, có dữ liệu đầu vào từ một DataSource, và sử dụng bộ giải mã để phân tích, giải mã, kết xuất trong từng giai đoạn của quá trình. Các PlayerProcesser cũng có thể được hiện thực và kế thừa từ các công cụ truyền thông đa phương tiện như MediaPlayer(Microsoft), RealPlayer(Real NetWork), HotMedia(IBM).

Lưu ý: trong JMF, ProcesserPlayer không cần thiết hỗ trợ plug-in. Plug-in không hoạt động trong môi trường của JMF1.0.

Trình diễn(Presentation):

Trong JMF, quá trình trình diễn là một mô hình được hiện thực từ các Controller. Controller định nghĩa cơ chế kiểm soát trạng thái và điều kiển cơ bản cho các đối tượng điều kiển, trình diễn và thu nhận dữ liệu truyền thông đa phương tiện dựa trên thời.Nó định nghĩa các giai đoạn mà bộ điều kiển hoạt động và cung cấp một cơ chế kiểm soát các giai đoạn chuyển đổi giữa các quá trình. Một hoạt động cần phải được thực hiện trước khi dữ liệu đa phương tiện theo thời gian có thể được trình diễn, vì vậy JMF cho phép kiểm soát các quá trình trên khi chúng xảy ra.

Một Controller có thể kiểm soát nhiều MediaEvent, và có thể cập nhật trong thái của nó. Để nhận được sự kiện từ một Controller, chẳng hạn như một Player, bạn cần hiện thực lớp ControllerListener.

Trong JMF, có hai dạng Controller: PlayerProcesser. PlayerProcesser được xây dựng cho một nguồn dữ liệu cụ thể và không thể tái sử dụng để trình diễn các luồng dữ liệu khác.

Các Controller trong JMF.

Player:

Một Player xử lý tại đầu vào của một luồng media data và kết xuất ra kết quả theo một thời gian chính xác. Một DataSource được sử dụng để cung cấp dữ liệu cho Player. Điểm kết xuất phụ thuộc vào từng loại dữ liệu truyền thông đang phương tiện được xử lý.

 

Mô hình xử lý của một Player trong JMF.

Player hỗ trợ nhiều phương thức kiểm soát từ người dùng và điều kiển bởi ClockController.

Mô hình kiểm soát của ControllerClock đối với Player.

Trạng thái của Player:

Một Player có thể có 1 trong 6 trạng thái. Clock xác định 2 trạng thái cơ bản: dừng(Stopped) và bắt đầu(Started). Để tạo điều kiện thuận lợi để quản lý tài nguyên, Controller xác định 5 trạng thái: Unrealized(chưa thực thi), Realizing(đang thực thi), Realized(đã thực thi), Prefetching(đang nạp), Prefetched(đã nạp).

Các trạng thái của Player.

Trong một quá trình tiêu chuẩn, một Player phải trải qua tất cả các trang thái trước khi đạt được trạng thái Started:

Một Player ở trạng thái Unrealized sẽ được khởi tạo, nhưng nó sẽ không được cấp phát bất cư tài nguyên nào. Và khi một Player được khởi tạo, nó luôn phải ở trạng thái Unrealizied.

khi phương thức reali được gọi, một Player sẽ thực hiện chuyển trạng thái từ Unrealizing sang trạng thái Realizing. Trong trạng thái Realizing, Player sẽ quyết định yêu cầu những loại tài nguyên nào. Trong quá trình này, Player chỉ được phép yêu cầu tài nguyên cần thiết và chỉ yêu cầu 1 lần. Tài nguyên yêu cầu có thể bao gồm tài nguyên dùng để kết xuất, chứ không nhất thiết là tài nguyên nội tại của hệ thống. (Độc quyền sử dụng tài nguyên có hạn chế, chẳng hạn như các thiết vị phần cứng chỉ có thể được cấp phát cho một Player tại một thời điểm, những tài nguyên như vậy sẽ được Player yêu cầu trong trạng thái Prefething). Một Player ở trạng thái Realizing thường thực hiện tải tài nguyên qua mạng.

Khi một Player kết thúc trạng thái Realizing, nó sẽ chuyển sang trạng thái Realized. Khi một Player đạt được trạng thái Realized, tức là nó đã biết được những loại tài nguyên cần thiết và biết được thông tin về loại dữ liệu sẽ trình diễn. Bởi vì Player ở trạng thái Realized, nó sẽ biết được là sao để kết xuất được dữ liệu, từ đó cung cấp các công cụ và phương thức điều kiển phù hợp. Nó sẽ thực hiện kết nối đến các đối tượng khác của hệ thống, tuy nhiên nó không gây cản trở việc khởi tạo của bất cứ Player nào khác.

Khi phương thức prefetch được gọi, Player sẽ chuyển từ trạng thái Realized sang trạng thái Prefetching. Một Player đang ở trạng thái Prefetching, tức là nó đang ở trạng thái chuẩn bị để trình diễn một luồng madia data.Trong giai đoạn này, Player sẽ chuẩn bị luồng media data, nhận nguồn tài nguyền danh riêng, và tất cả những gì cần thiết để chuẩn bị trình diễn. Trạng thái Prefetching phải được lặp lại, nếu Player nhận được yêu cầu thay đổi vị trí trình diễn hoặc tốc độ trình diễn luồng media data, nó có thể thực hiện bổ sung thêm bộ đệm hay các cơ chế xử lý cần thiết.

Khi phương thức start được gọi, Player sẽ bước vào trạng thái Started. Khi Player ở trạng thái Started, Clock của nó sẽ hoạt động, Time-Base và Media-Time được tính toán. Trên thực tế, Player phải trải qua một thời gian đợi nào đó, trước khi bắt đầu trình diễn.

Một Player gởi một TransitionEvent, khi nó chuyển từ trạng thái này sang trạng thái khác. Một thể hiện của ControllerListener cung cấp cho chương trình của bạn khả năng xác định trạng thái hiện tại của Player và để có thao tác phù hợp. Ví dụ: khi chương trình của bạn gọi một phương thức bất đồng bộ trong một Player hay một Processer, bạn cần xác định sự kiện nào xảy ra khi một quá trình xử lý kết thúc.

Sử dụng cơ chế quản lý theo sự kiện, bạn có thể quản lý độ trễ của một Player, bằng cách kiểm soát thời gian bắt đầu của trạng thái Realizing và Prefetching. Nó cũng cho phép bạn phương thức phù hợp ứng với trạng thái hiện tại của Player.

Các phương thức trong từng trạng thái của Player:

Không phải tất cả các phương thức đều được gọi ở bất cứ trạnh thái nào của Player. JMF hạn chế các phương thức tùy thuộc vào từng trạng thái của Player. Nếu bạn gọi một phương thức không phù hợp với trạng thái hiện tại của Player, nó sẽ “ném” ra biệt lệ tương ứng:

           Trạng thái

Phương

thức

Unrealized Realized Prefetched Started
addController NotRealizedError legal legal ClockStartedError
deallocate legal legal legal ClockStartedError
getControlPanelComponent NotRealizedError legal legal legal
getGainControl NotRealizedError legal legal legal
getStartLatency NotRealizedError legal legal legal
getTimeBase NotRealizedError legal legal legal
getVisualComponent NotRealizedError legal legal legal
mapToTimeBase ClockStoppedException ClockStoppedException ClockStoppedException legal
removeController NotRealizedError legal legal ClockStartedError
setMediaTime NotRealizedError legal legal legal
setRate NotRealizedError legal legal legal
setStopTime NotRealizedError legal legal StopTimeSetError

(nếu được thiết lập trước đó)

setTimeBase NotRealizedError legal legal ClockStartedError
syncStart NotRealizedError NotPrefetchedError legal ClockStartedError

 

Processer:

Một Processer cũng được dùng để trình diễn một luồng media data. Processer là một dạng đặc biệt của Player, nó cung cấp khả năng kiểm soát tất cả quá trình xử lý đầu vào của một luồng media data. Một Processer hỗ trợ tất cả các kiểu điều kiển trình diễn như của một Player.

Mô hình của một Processer.

Ngoài khả năng kết xuất dữ liệu đến các thiết bị đầu ra, một Processer còn có thể kết xuất dữ liệu đến một DataSource, để từ đó, dữ liệu có thể được xử lý tiếp bằng một Player hay một Processer khác, hoặc có thể đi đến những điểm đầu cuối khác, ví dụ: có thể dùng để lưu vào một tập tin.

Điều kiển trình diễn:

Ngoài khả năng cung cấp điều kiển trình diễn bằng Controller, một Player hoặc một Processer còn có thể cung cấp khả năng điều kiển trĩnh diễn lại. Nếu muốn làm như vậy, trước hết, bạn còn có một từ Player hoặc một Porcesser một GainControll bằng cách gọi phương thức getGainControll. Một đối tượng GainControll sẽ cung cấp một GainChangeEvent bất cứ khi nào nó bị thay đổi. Bằng cách hiện thức lớp GainChangeListener, bạn có thể bắt được các thay đổi này. Ví dụ: bạn cập nhật thông tin từ từ một Component.

Trong Player hoặc Processer, tùy thuộc vào từng loại Control, chúng có thể cung cấp cho bạn các hành vi điều kiển của người dùng, cũng như khả năng tùy chỉnh các công cụ giao tiếp với họ. Bạn có thể truy cập các bộ điều kiển này qua phương thức getControls.

Ví dụ: lớp thể hiện CachingControl là một kế thừa của lớp Control, nó cung cấp một cơ chế hiển quá trình tải về trên một thanh tiền trình. Nếu một Player có thể thông báo về tiến độ tải về của nó, nó sẽ sử dụng phương thức này. Để xem một Player có hỗ trợ phương thức CachingControl hay không, bạn có thể gọi phương thức getControl(CachingControl) hoặc sử dụng getControls để xem danh sách bộ điều kiển.

Các cộng cụ giao tiếp người dùng

Một Player hay Processer thường cung cấp 2 công cụ giao tiếp người dùng tiêu chuẩn: công cụ bằng hình ảnh hoặc một bảng điều kiển. Bạn có thể truy cập trực tiếp thông qua phương thức getVisualComponentgetControlComponent.

Bạn cũng có thể tùy chỉnh các công cụ này và sử dụng cơ chế “lắng nghe” để xác định khi nào chúng có thay đổi.

Các sự kiện điều kiển:

Các sự kiện ControllerEvent sẽ được gửi bởi một Controller như Player hay Processer khi chúng rơi vào một trong ba trường hợp sau: chúng có sự thay đổi nội tại, TransitionEvents và ControllerClosedEvent:

Các sự kiện khi xảy ra sự thay đổi gồm: RateChangeEvent, DurationUpdateEvent, và FormatChangeEvent…. Các sự kiện này sẽ được thông báo khi các thuộc tính của một Controller bị thay đổi. Ví dụ: một Player sẽ thông báo một sự kiện RateChangeEvent khi chỉ số tốc độ trình diễn của nó bị thay đổi, thông qua phương thức setRate.

Các sự kiện TransitionEvent cho phép chương trình của bạn theo dõi và đáp ứng những thay đổi trạng thái của một Controller. Ví dụ: một Player sẽ thông báo các sự kiện TransitionEvent khi nó chuyển từ trạng thái này sang trạng thái khac.

Các sự kiện ControllerClosedEvent sẽ được Controller thông báo trước khi nó đóng. Một khi Controller thông báo sự kiện ControllerClosedEvent thì nó không thể còn được sử dụng. Một sự kiện ControllerClosedError là một trường hợp đặc biệt của ControllerClosedEvent. Khi bạn nhận được một ControllerClosedError, bạn có thể có được những phản ứng phù hợp để kiểm soát những trục trặc và giảm thiểu những tác động từ phía người dùng.

Mô hình quản lý sự kiện trong JMF.

Tiến trình:

Một Processer là một Player có một DataSource ở đầu vào, thực hiện một số tiến trình xử lý được định nghĩa bởi người dùng và đầu ra là một luồng media data đã được xử lý:

Mô hình tiến trình xử lý trong JMF.

Một Processer có thể gửi dữ liệu đầu ra đến một thiết bị trình diễn hay một DataSource. Nếu dữ liệu được gửi tới một DataSource, thì DataSource này có thể được sử dụng cho một Player hay một Porcesser khác như một nguồn dữ liệu đầu vào, hoặc có thể dùng làm dữ liệu cho một DataSink.

Trong khi một tiến trình được xử lý bởi một Player được định nghĩa bởi một thể hiện, thì một Porcesser cho phép người lập trình định nghĩa loại tiến trình được áp dụng với luồng media data. Điều này cho phép phối hợp các hiệu ứng, ghép và bố cục lại luồng dữ liệu.

Một tiến trình xử lý luồng media data được thực hiện qua nhiều gia đoạn:

Tiến trình bên trong một Processer.

Tách kênh(Demultiplexing) là một quá trình phân tích luồng dữ liệu đầu vào. Nếu một luồng có chứa nhiều kênh, các kênh này sẽ được chiết xuất và xử lý một cách riêng biệt. Ví dụ: Một tập tin QuickTime có thể được tách kênh thành kênh âm thanh và kênh hình ảnh. Quá trình tách kênh sẽ được tữ động thực hiện, bất cứ khi nào, luồng dữ liệu đầu vào là một luồng media data ghép.

Tiền xử lý(Pre-processing) là quá trình áp dụng các thuật toán hữu ích tương ứng với từng kênh dữ liệu đầu vào.

Chuyển mã(Transcoding) là quá trình chuyển đổi từ kênh media data từ một định dạng đầu vào thành một định dạng khác. Một quá trình giải nén một luồng media data cũng được coi là một quá trình giải mã(deconding). Và ngược lại, quá trình nén một luồng media data cũng được coi là một quá trình mã hóa(encoding).

Hậu xử lý(Post-processing) là quá trình áp dụng các thuật toán cần thiết để giải mã các kênh.

Ghép kênh(Multiplexing) là một quá trình ghép các kênh media data vào một luồng media data duy nhất. Ví dụ: các kênh hình ảnh và âm thanh riêng biệt có thể được ghép vào một luồng dữ liệu dạng MPEG-1. Bạn chỉ định dạng dữ liệu kết xuất bằng phương thức setOutputContentDescriptor.

Kết xuất(Rendering) là quá trình trình bày các kênh media data ra cho người dùng.

Việc xử lý ở từng giai đoạn được thực hiện bởi những thành phần riêng biệt. Những thành phần đó là những plug-in được cung cấp sẵn trong JMF. Nếu Processer hỗ trợ các phương thức TrackControl, bạn có thể chọn plug-in phù hợp cho từng kênh dữ liệu:

Demultiplexer: thực hiện phân tích các luồng media data như WAV, MPEG, QuickTime. Nếu luồng media data là luồng ghép, nó sẽ thực hiện tách luồng này thành những kênh riêng biệt.

Effect:  thực hiện xử lý các hiệu ứng đặc biệt trên từng kênh dữ liệu.

Codex: thực hiện mã hóa và giải mã.

Mutiplexer: thực hiện kết hợp nhiều kênh riêng biệt vào một luồng media data duy nhất.

Renderer: xử lý từng kênh media data, kết xuất dữ liệu đến các điểm đầu cuối như loa và màn hình.

Các trạng thái của Processer:

Một Processer có hai trạng thái chuẩn bị cơ bản, Configuring(đang cấu hình) và Configured(đã cấu hình), xảy ra trước khi Processer vào trạng thái Realizing

Trạng thái của Processer.

Processer sẽ vào trạng thái Configuring khi nó gọi phương thức configure. Khi một Processer ở trạng thái Configuring, nó sẽ kết nối tới một DataSource, thực hiện tách kênh trên luồng dữ liệu đầu vào và xác định định dạng của dữ liệu đầu vào.

Processer sẽ ở trạng thái Configured khi náo đã hoàn thành kết nối đến một DataSource và xác định xong định dạng của dữ liệu. Khi Processer đạt được trạng thái nó sẽ thông báo một sự kiện ConfigureCompleteEvent.

Khi phương thức realize được gọi, Processer sẽ chuyển sang trạng thái Realized.

Khi Processer ở trạng thái Configured, để gọi có được đối tượng TrackControl của các kênh trong luồng media data hiện hành, bạn có thể gọi tới phương thức getTrackControls. Những đối tượng TrackControl này cho phép bạn xác định những hoạt động xử lý mà bạn mong muốn bên trong Processer.

Khi phương thức realize được gọi bên trong một Processer đang ở trạng thái Unrealized, nó cho phép Processer nay chuyển từ trạng thái Configuring hay Configured sang trạng thái Realized.

Không thể truy cập đến các TrackControl của một luồng media data bên trong một Processer đang ở trạng thái Realized.

Các phương thức trong từng trạng thái của Processer:

Processer là một dạng đặc biệt của Player, nên một số phương thức bên trong của một Player cũng có thể được gọi cho một Processer. Ngoài ra, một Processer còn sở hữu một số phương thức đặc biệt. Bảng sau cho ta thấy các phương thức có thể được gọi trong từng trạng thái của một Processer, nếu phương thức được gọi không phù hợp với trạng thái hiện tại hoặc xảy ra lỗi, nó sẽ trả về một biệt lệ tương ứng.

           Trạng thái

Phương

thức

Unrealized Configuring Configured Realized
addController NotRealizedError NotRealizedError NotRealizedError legal
deallocate legal legal legal legal
getControlPanelComponent NotRealizedError NotRealizedError NotRealizedError legal
getControls legal legal legal legal
getDataOutput NotRealizedError NotRealizedError NotRealizedError legal
getGainControl NotRealizedError NotRealizedError NotRealizedError legal
getOutputContentDescriptor NotConfiguredError NotConfiguredError legal legal
getStartLatency NotRealizedError NotRealizedError NotRealizedError legal
getSupportedContentDescriptors legal legal legal legal
getTimeBase NotRealizedError NotRealizedError NotRealizedError legal
getTrackControls NotConfiguredError NotConfiguredError legal FormatChangeException
getVisualComponent NotRealizedError NotRealizedError NotRealizedError legal
mapToTimeBase ClockStoppedException ClockStoppedException ClockStoppedException ClockStopedException
realize legal legal legal legal
removeController NotRealizedError NotRealizedError NotRealizedError legal
setOutputContentDescriptor NotConfiguredError NotConfiguredError legal FormatcChangeException
setMediaTime NotRealizedError NotRealizedError NotRealizedError legal
setRate NotRealizedError NotRealizedError NotRealizedError legal
setStopTime NotRealizedError NotRealizedError NotRealizedError legal
setTimeBase NotRealizedError NotRealizedError NotRealizedError legal
syncStart NotPrefetchedError NotPrefetchedError NotPrefetchedError NotPrefetchedError

Các phương thức bên trong Processer.

Kiển soát tiến trình

Bạn có thể kiểm soát những hoạt động cần thiết của Processer thông qua TrackControl đối với từng kênh cụ thể. Bạn gọi tới phương thức getTrackControls để có được danh sách các TrackControl hiện hành bên trong Processer.

Thông qua một đối tượng TrackControl, bạn có thể chọn bộ hiệu ứng, bộ mã hóa hay bộ kết suất tùy ý với kênh mà bạn chọn. Để tìm ra được những công cụ này, bạn có thể truy vấn đối tượng PlugInManager.

Để kiểm soát quá trình chuyển mã được thực hiện trên một kênh được thực hiện bởi Codec, bạn có thể có được đối tượng điều kiển cho từng kênh bằng cách gọi phương thức getControls cho từng đối tượng TrackControl.  Phương thức này trả về các đối tượng điều kiển cho từng kênh như BitRateControlQualityControl.

Nếu bạn muốn xác định định dạng cho dữ liệu đầu ra, bạn có thể gõi tới phương thức setFormat để xác định định dang mang muốn và cho phép Processer xác định bộ mã hóa và kết xuất thích hợp. Ngoài ra, bạn có thể chỉ định kiểu dữ liệu đầu ra bằng cách: bạn có thể khởi tạo một Processer bằng cách sử dụng một ProcesserModel. Một ProcesserModel xác định các kiểu dữ liệu đầu vào và đầu ra cho một Processer. Khi một ProcesserModel thông qua một Manager để tạo một Processer, bạn có thể quản lý tốt hơn dữ liệu đầu vào và đầu ra.

Dữ liệu đầu ra:

Phương thức getDataOutput trả về một DataSource đầu ra của một Processer. DataSource này có thể được sử dụng cho một Player hay một Processer khác hoặc là nguồn dữ liệu cho một DataSink.

Một DataSource đầu ra của Processer có thể ở bất dạng nào sau đây: PushDataSource, PushBufferDataSource, PullDataSource, PullBufferDataSource.

Về bản chất, Processer là một Player.

Thu

Một thiết bị thu dữ liệu truyền thông đa phương tuện có thể được coi như một nguồn cung cấp dữ liệu. Ví dụ: một microphone có thể nắm bắt âm thanh đầu vào hay một máy quay video kỹ thuât số có thể cung cấp các kỹ thuật thu hình khác nhau. Các thiết bị này có thể gọi tắt là nguồn dữ liệu(DataSource). Ví dụ: một thiết bị có thể cung cấp dữ liệu có thể coi là một PushDataSource. Bất kỳ DataSource có thể được sử dụng như  một trong các loại nguồn dữ liệu sau: PushDataSource, PushBufferDataSource, PullDataSource, PullBufferDataSource.

Một số thiết bị cho phép cung cấp những luồng media data kép. Ví dụ: một luồng dữ liệu thu từ buổi truyền hình trực tiếp có thể cung cấp cả kênh hình và kênh âm thanh. DataSource tương ứng nhiều SourceStream được cung cấp thiết bị thu.

Lưu trữ và truyền tải luồng media data

Một DataSink được sử dụng để đọc dữ liệu lên từ một DataSource hoặc là điểm đến của một luồng media data(không phải đến các thiết bị kết xuất). Một DataSink có thể được lưu thành một tập tin trên hệ thông, có thể được gửi vào mạng(Internet) hoặc có thể được truyền tải trực tuyến thời gian thực bằng phương thức RTP.

Giống như Player, DataSink được xây dựng để quản lý thông qua Manager bằng một DataSource. Một DataSink có thể sử dụng một StreamWriterControl để ghi thành tập tin.

Kiểm soát lưu trữ:

Một DataSink có thể thông báo tình trạng của nó thông qua sự kiện DataSinkEvent. Có các loại DataSinkEvent như sau:

DataSinkErrorEvent: chỉ ra rằng có lỗi khi tiến hành ghi dữ liệu từ DataSink.

EndOfStreamEvent: chỉ ra rằng luồng dữ liệu đã được ghi thành công.

Đế có thể bắt được các sự kiện này, bạn cần có một thể hiện của lớp DataSinkListener.

Leave a Reply