Tìm hiểu cơ bản về Gstreamer và Deepstream SDK

0 0 0

Người đăng: Huy Vũ

Theo Viblo Asia

Xin chào các bạn đây là bài viết đầu tay của mình, bài viết này sẽ nói cơ bản về các plugins có trong một pipeline cơ bản của Deepstream SDK, đây là session 1 của mình về đề tài này mong các bạn sẽ vui vẻ khi đọc nó, mong muốn các bạn sẽ giúp mình thêm khi kiến thức của mình có thể bị sai lệch ở đâu. Mọi thứ mình tổng hợp ở bài viết này đều là từ docs của Gstreamer và Deepstream SDK.

GsTreamer là gì?

GsTreamer là:

  • Một framework đa phương tiện đa nền tảng, được thiết kế để xử lý và quản lý các luồng dữ liệu đa phương tiện như âm thanh, video, và các dạng dữ liệu tương tự. Nó được phát triển lần đầu tiên vào năm 1999 bởi Erik Walthinsen, với mục tiêu tạo ra một công cụ mạnh mẽ, dễ mở rộng và linh hoạt cho các ứng dụng xử lý đa phương tiện.

  • GStreamer là một framework (khung phát triển phần mềm) dùng để xây dựng các ứng dụng xử lý và phát truyền media (âm thanh và video). Cơ sở thiết kế của GStreamer bắt nguồn từ pipeline video tại Oregon Graduate Institute và có ảnh hưởng từ DirectShow.

  • GStreamer cung cấp một pipeline-based processing framework (khung xử lý dựa trên pipeline), nơi dữ liệu đa phương tiện được xử lý qua các element (thành phần) riêng lẻ. Mỗi element thực hiện một nhiệm vụ cụ thể, chẳng hạn như:

    • Đọc dữ liệu từ nguồn (file, camera, microphone, mạng).
    • Mã hóa hoặc giải mã dữ liệu (codec).
    • Áp dụng hiệu ứng (filter).
    • Xuất dữ liệu (hiển thị trên màn hình, phát qua loa, hoặc lưu vào file).
  • Dữ liệu trong GStreamer được xử lý theo dạng blockstream (khối dữ liệu tuần tự), giúp tiết kiệm bộ nhớ và đảm bảo hiệu suất cao ngay cả khi xử lý các file lớn hoặc dữ liệu theo thời gian thực.

Cấu trúc của GStreamer:

  • Các thành phần trong GStreamer:
  • Sources: Dùng để lấy dữ liệu đầu vào từ các nguồn khác nhau, ví dụ như từ file, camera, hoặc mạng.
  • Formats: Bao gồm các thành phần như parsers (phân tích định dạng), muxers/demuxers (gộp và tách các luồng media), metadata, subtitles.
  • Codecs: Bao gồm các bộ mã hóa (encoder) và giải mã (decoder) dữ liệu media.
  • Filters: Các bộ lọc cho phép chuyển đổi định dạng, trộn âm thanh/video, hoặc áp dụng các hiệu ứng.
  • Sinks: Các thành phần xuất dữ liệu, ví dụ như hiển thị video hoặc phát âm thanh.
- Các gói GStreamer: + gstreamer: Gói core chứa các chức năng cơ bản. + gst-plugins-base: Một bộ các elements mẫu và thiết yếu. + gst-plugins-good: Các plugin có chất lượng tốt, được cấp phép LGPL. + gst-plugins-ugly: Các plugin có chất lượng tốt nhưng có thể gặp vấn đề trong phân phối (vấn đề bản quyền). + gst-plugins-bad: Các plugin cần cải thiện về chất lượng. + gst-libav: Các plugin bao bọc libav cho việc mã hóa và giải mã.
  1. Elements (Các phần tử)
    • Element là đối tượng quan trọng nhất trong GStreamer. Mỗi element thực hiện một nhiệm vụ cụ thể, chẳng hạn như đọc dữ liệu từ một file, giải mã dữ liệu, hoặc xuất dữ liệu ra thiết bị đầu ra như sound card.
    • Khi kết hợp nhiều element lại với nhau, ta tạo thành một pipeline để thực hiện một công việc cụ thể, ví dụ như phát lại media hoặc ghi lại media.
    • GStreamer đi kèm với một bộ sưu tập lớn các element, cho phép phát triển đa dạng các ứng dụng media. Ngoài ra, nếu cần thiết, người dùng có thể viết thêm các element mới để mở rộng khả năng của GStreamer.
  2. Pads (Cổng kết nối)
    • Pads là các cổng vào và ra của một element, nơi bạn có thể kết nối các element khác. Pads giúp đàm phán các liên kết và dữ liệu truyền qua giữa các element trong GStreamer.
    • Mỗi pad có các khả năng xử lý dữ liệu riêng. Chẳng hạn, một pad có thể giới hạn loại dữ liệu mà nó chấp nhận. Các liên kết giữa các pad chỉ được phép nếu các kiểu dữ liệu (capabilities) của chúng tương thích với nhau.
    • Caps negotiation là quá trình thương lượng kiểu dữ liệu giữa các pad.
      • Ví dụ so sánh: Một pad giống như một jack cắm trên các thiết bị điện tử. Ví dụ, bạn có thể kết nối đầu ra âm thanh của đầu DVD vào loa vì cả hai đều có jack âm thanh tương thích. Nhưng bạn không thể kết nối đầu DVD vào máy chiếu vì chúng có các loại cổng khác nhau. Pads trong GStreamer thực hiện vai trò tương tự.
  3. Bins và Pipelines
    • Bin là một container chứa các element. Một bin thực sự là một subclass của element, vì vậy bạn có thể kiểm soát bin như thể nó là một element. Điều này giúp giảm bớt sự phức tạp khi làm việc với nhiều element.
    • Pipeline là một loại bin đặc biệt, nó là bin cấp cao nhất trong GStreamer. Pipeline quản lý bus (đường truyền tin) cho ứng dụng và đồng bộ hóa các hoạt động của các element con. Khi pipeline ở trạng thái PAUSED hoặc PLAYING, dữ liệu sẽ bắt đầu chảy qua các element và quá trình xử lý media sẽ diễn ra.
    • Pipeline chạy trong một luồng riêng biệt (thread), và sẽ tiếp tục chạy cho đến khi bạn dừng nó hoặc khi dòng dữ liệu kết thúc.
  4. Communication (Giao tiếp)
    • GStreamer cung cấp nhiều cơ chế để giao tiếp và trao đổi dữ liệu giữa ứng dụng và pipeline:
      • Buffers: Là đối tượng dùng để truyền dữ liệu streaming giữa các element trong pipeline. Buffers luôn di chuyển từ source (nguồn) đến sink (đích), tức là từ upstream xuống downstream.
      • Events: Là các đối tượng được gửi giữa các element hoặc từ ứng dụng đến các element. Các sự kiện có thể di chuyển lên (upstream) hoặc xuống (downstream). Các sự kiện đi xuống có thể được đồng bộ với dòng dữ liệu.
      • Messages: Là các đối tượng được các element gửi lên message bus của pipeline, nơi chúng sẽ được giữ lại để ứng dụng thu thập. Các message có thể bao gồm thông tin như lỗi, thay đổi trạng thái, trạng thái bộ đệm, hoặc các yêu cầu điều hướng khác.
      • Messages thường được xử lý asynchronously (bất đồng bộ) từ luồng chính của ứng dụng, nhưng có thể bị bắt synchronously (đồng bộ) trong bối cảnh luồng streaming của element gửi message.
      • Queries: Là các yêu cầu thông tin từ ứng dụng tới pipeline, ví dụ như yêu cầu về độ dài của media hay vị trí phát lại hiện tại. Queries luôn trả lời đồng bộ. Các element trong pipeline cũng có thể sử dụng queries để yêu cầu thông tin từ các element khác (ví dụ: kích thước file hoặc thời gian của media).

Pipeline GStreamer:

  1. File SRC:
    • Chức năng: Đọc file phương tiên từ nhiều nguồn và đa dạng dđiịnh dạng như âm thanh (MP3, OGG, WAV) hoặc video (MP4, AVI).
    • Đọc dữ liệu: filesrc sẽ đọc dữ liệu từ file theo dạng byte-stream (dòng byte).
      • Dữ liệu đọc được là dạng chưa giải mã và có thể là dữ liệu thô, chưa có cấu trúc (như trong trường hợp một file video chưa được phân tách thành các luồng âm thanh và video).
    • Truyền dữ liệu vào pipeline:
      • Khi filesrc đọc một lượng dữ liệu nhất định, nó đóng gói dữ liệu này vào một buffer và chuyển tới phần tử tiếp theo.
      • Xử lý một file đa phương tiện, dữ liệu này có thể được gửi đến một demuxer (như oggdemux), nơi dữ liệu sẽ được tách thành các luồng âm thanh và video riêng biệt.
      • Các dữ liệu này có thể là một loạt các buffers (được mô tả bởi GstBuffer), mà sẽ tiếp tục được xử lý trong các phần tử kế tiếp.
    • Điều khiển luồng dữ liệu:
      • GStreamer cung cấp cơ chế capabilities negotiation giữa các phần tử trong pipeline để xác định loại dữ liệu sẽ được chuyển giao giữa các phần tử.
      • Ví dụ: filesrc có thể đọc một file OGG, và khi dữ liệu được chuyển vào phần tử tiếp theo (như oggdemux), phần tử này sẽ xác định các luồng audio và video có trong file OGG.
    • Ví dụ code: filesrc location=yourfile.ogg
  2. OGG-Demuxer:
    • Định nghiĩa: oggdemux là một phần tử demuxer trong GStreamer được thiết kế để tách (demux) các luồng âm thanh và video từ các tệp có định dạng OGG. Đây là bước quan trọng trong việc xử lý các tệp đa phương tiện, khi dữ liệu âm thanh và video cần được tách ra để xử lý tiếp theo bởi các phần tử giải mã (decoders) và phát lại.

    • Chức năng:

      • Có nhiệm vụ tách các luồng âm thanh và video từ file OGG. Các tệp OGG có thể chứa nhiều luồng dữ liệu khác nhau, bao gồm âm thanh (ví dụ, Vorbis) và video (ví dụ, Theora).
      • Sau khi tách, oggdemux sẽ gửi các luồng này đến các phần tử giải mã tương ứng để xử lý tiếp (ví dụ: gửi luồng âm thanh vào phần tử vorbisdec và luồng video vào theoradec).
    • Cách thức hoạt động:

      • Nhận dữ liệu đầu vào: nhận dữ liệu đầu vào từ phần tử trước đó trong pipeline (trong trường hợp này là filesrc). Dữ liệu đầu vào là một luồng byte (raw stream) của tệp OGG, chứa các thông tin về nhiều luồng âm thanh, video, metadata, v.v
      • Phân tích tệp OGG: Khi nhận được dữ liệu, oggdemux phân tích cấu trúc của tệp OGG. Tệp OGG có thể chứa một hoặc nhiều luồng âm thanh và video, tùy thuộc vào nội dung của tệp.

      Oggdemux sẽ tìm kiếm các phần tử trong tệp như: thông tin của các luồng âm thanh (ví dụ: Vorbis), video (ví dụ: Theora), và các luồng khác như chú thích, metadata, hoặc phụ đề.

      • Tách các luồng dữ liệu: Sau khi phân tích xong tệp, oggdemux sẽ tách các luồng dữ liệu. Mỗi luồng sẽ được xử lý riêng biệt. Ví dụ: . Các luồng âm thanh Vorbis sẽ được chuyển đến phần tử vorbisdec (Vorbis decoder). . Các luồng video Theora sẽ được chuyển đến phần tử theoradec (Theora decoder). Mỗi luồng được tách ra sẽ có dạng GstPad, và oggdemux sẽ tạo ra các source pads cho từng luồng, cho phép chúng được kết nối với các phần tử khác trong pipeline.** GstPad: là một trong những khái niệm cốt lõi trong GStreamer, giúp các phần tử (elements) trong pipeline kết nối và giao tiếp với nhau. -> Có thể xem GstPad như là các cổng vào và ra của một phần tử, cho phép truyền dữ liệu giữa các phần tử trong pipeline.
      • Mỗi phần tử trong GStreamer có thể có nhiều pad (cổng vào và ra), mỗi pad có thể là input pad hoặc output pad.
      • Input pad (sink pad): Nhận dữ liệu từ phần tử khác.
      • Output pad (source pad): Gửi dữ liệu đến phần tử khác.
      • Cấu trúc và chức năng:
      • Caps (Capabilities): Mỗi pad có một bộ mô tả khả năng (caps), xác định kiểu dữ liệu mà nó có thể xử lý. ~ Caps negotiation: Khi kết nối giữa hai pads được thực hiện, GStreamer sẽ sử dụng caps để đảm bảo rằng loại dữ liệu mà mỗi pad có thể xử lý là tương thích với nhau. Quá trình này gọi là caps negotiation. ~ Ví dụ, một input pad có thể chỉ nhận dữ liệu âm thanh với định dạng cụ thể như audio/x-vorbis.
      • Direction: ~ Sink Pad: Chấp nhận dữ liệu từ phần tử khác (dữ liệu sẽ đi vào phần tử). ~ Source Pad: Gửi dữ liệu đi tới phần tử khác (dữ liệu sẽ đi ra khỏi phần tử).
      • Buffer và Event: ~ Buffer: Dữ liệu thực tế được truyền qua pad. Buffer có thể là âm thanh, video hoặc bất kỳ loại dữ liệu nào mà phần tử xử lý. ~ Event: Các sự kiện cũng có thể được truyền qua các pad, chẳng hạn như thay đổi trạng thái, đóng hoặc mở luồng, hoặc các sự kiện đồng bộ hóa.
      • Link: GstPad là thành phần then chốt để kết nối các phần tử trong pipeline. Khi bạn kết nối một output pad của phần tử này với input pad của phần tử khác, dữ liệu sẽ bắt đầu chảy từ phần tử này sang phần tử kia.
      • Cách hoạt đông:
      • Kết nối giữa các phần tử trong pipeline thực chất là quá trình kết nối các pads của các phần tử. Cụ thể, GStreamer sử dụng các phương thức như gst_pad_link() để kết nối hai pad với nhau.
      • Ví dụ: ~ Giả sử bạn có hai phần tử: một phần tử video decoder (giải mã video) và một phần tử video sink (hiển thị video). Video decoder có một source pad để xuất ra video đã giải mã và video sink có một sink pad để nhận video. ~ Bạn có thể kết nối pad của phần tử decoder với pad của phần tử sink để dữ liệu video được truyền đi.
      • Quản lý thông tin của các luồng: oggdemux có thể phát hiện và chỉ định loại codec cho từng luồng (ví dụ: xác định luồng âm thanh là Vorbis hoặc luồng video là Theora).

      Thông tin này được truyền qua các GstCaps (caps - capabilities), giúp các phần tử giải mã biết cách xử lý dữ liệu đúng cách.

      • Phát dữ liệu tách ra: Các luồng đã được tách sẽ được truyền tiếp vào các phần tử giải mã như: . vorbisdec cho giải mã âm thanh Vorbis. . theoradec cho giải mã video Theora.

      Dữ liệu đã được giải mã sẽ tiếp tục được xử lý, chẳng hạn như phát lại âm thanh qua audio sink hoặc hiển thị video qua video sink.

3.1. Vorbis-decoder:

  • Định nghĩa: là phần tử GStreamer dùng để giải mã các luồng âm thanh được nén bằng định dạng Vorbis, có mặt phổ biến trong các file OGG. Mục tiêu của phần tử này là chuyển đổi dữ liệu âm thanh đã mã hóa thành định dạng âm thanh thô mà các phần tử tiếp theo trong pipeline có thể xử lý.
  • Cách hoạt động:
  • Đầu vào: Sau khi oggdemux tách dữ liệu âm thanh (dạng Vorbis) từ file OGG, dữ liệu này sẽ được truyền vào vorbisdec qua một sink pad.
  • Giải mã: vorbisdec sử dụng thuật toán giải mã của Vorbis để chuyển dữ liệu từ dạng nén (mã hóa) thành một dạng âm thanh thô, ví dụ, PCM (Pulse Code Modulation) - một dạng âm thanh không nén.
  • Đầu ra: Sau khi giải mã, dữ liệu âm thanh thô (PCM) sẽ được gửi ra qua các source pad của vorbisdec, để truyền cho các phần tử tiếp theo, ví dụ như audio sink để phát ra âm thanh.
  • Quá trình giải mã:
  • Dữ liệu âm thanh nén trong file OGG được lưu trữ dưới dạng các khối dữ liệu nén. Phần tử vorbisdec nhận các khối này và giải nén chúng thành các mẫu âm thanh (samples).
  • vorbisdec sẽ xác định các thông tin cần thiết như tốc độ mẫu (sampling rate), số kênh (channels), và bit depth của âm thanh thô, từ đó giải mã và đưa ra luồng âm thanh phù hợp.

3.2. Theora_decoder:

  • Định nghĩa: là phần tử giải mã video sử dụng định dạng mã hóa video Theora, một định dạng video nén mã nguồn mở thường được sử dụng cùng với định dạng âm thanh Vorbis trong các file OGG.
  • Cách hoạt động:
  • Đầu vào: Sau khi oggdemux tách luồng video Theora từ file OGG, dữ liệu video nén sẽ được chuyển qua theoradec.
  • Giải mã: Tương tự như phần tử vorbisdec, phần tử theoradec nhận dữ liệu video mã hóa và giải mã nó thành các khung hình (frames) video.
  • Đầu ra: Các khung hình giải mã được sau đó sẽ được truyền qua các source pad của theoradec và đưa tới các phần tử tiếp theo, như video sink để hiển thị video.
  • Quá trinh giải mã:
  • Dữ liệu video trong định dạng Theora được nén theo thuật toán mã hóa video Theora. Khi dữ liệu này được chuyển vào theoradec, phần tử này sẽ giải mã các khung hình video từ dữ liệu nén thành các khung hình video thô.
  • Sau khi giải mã, các khung hình video được lưu trữ dưới dạng bitmap hoặc các định dạng pixel khác, sẵn sàng để hiển thị trên màn hình hoặc xử lý thêm.

4.1 Audio-sink:

  • Định nghĩa: là một phần tử GStreamer được thiết kế để tự động chọn thiết bị phát âm thanh phù hợp dựa trên hệ thống hiện tại (ví dụ: ALSA trên Linux, DirectSound trên Windows, CoreAudio trên macOS, v.v.).
  • Cách hoạt động:
  • Đầu vào: Sau khi dữ liệu âm thanh được giải mã từ phần tử vorbisdec, nó sẽ được gửi đến autoaudiosink. Dữ liệu này thường ở dạng âm thanh thô (PCM).
  • Lựa chọn thiết bị: Phần tử autoaudiosink tự động lựa chọn một thiết bị âm thanh thích hợp để phát âm thanh. Nó sẽ tìm kiếm các thiết bị phát âm thanh có sẵn trên hệ thống, chẳng hạn như loa, tai nghe hoặc các thiết bị âm thanh ngoài như DAC (Digital-to-Analog Converter).
  • Phát âm thanh: Khi autoaudiosink nhận dữ liệu âm thanh (thường là dạng PCM, không nén), nó sẽ xử lý và phát nó qua thiết bị đã chọn. Dữ liệu âm thanh sẽ được truyền dưới dạng một dòng các mẫu âm thanh theo tần số mẫu, số kênh (stereo hoặc mono), và độ phân giải bit (16 bit, 24 bit, v.v.). Phần tử này sẽ đảm nhiệm việc phát âm thanh qua hệ thống, điều chỉnh theo nhu cầu của hệ điều hành.
  • Cơ chế đồng bộ (synchronization): autoaudiosink có thể đồng bộ hóa âm thanh phát ra với các yếu tố khác trong pipeline, chẳng hạn như video, để đảm bảo cả âm thanh và hình ảnh được phát đúng thời gian.
  • Quá trình hoạt động:
  • Dữ liệu âm thanh thô (PCM) sẽ được gửi qua autoaudiosink, và phần tử này sẽ chuyển đổi nó thành tín hiệu âm thanh mà hệ thống có thể phát ra qua thiết bị đã chọn.
  • Quá trình này hoàn toàn tự động, không cần người dùng phải can thiệp, và GStreamer sẽ chọn thiết bị âm thanh phù hợp dựa trên cấu hình hệ thống.

4.2 Video-sink:

  • Định nghĩa: là một phần tử GStreamer dùng để tự động chọn thiết bị hiển thị video thích hợp, như X11, OpenGL, hoặc DirectX, tùy thuộc vào hệ thống đang chạy (Linux, macOS, Windows).
  • Cách hoạt động:
  • Đầu vào: Sau khi dữ liệu video đã được giải mã từ phần tử theoradec (video Theora), nó sẽ được gửi đến autovideosink. Dữ liệu này thường ở dạng các khung hình (frames), thường được lưu trữ dưới dạng hình ảnh bitmap hoặc pixel buffer.
  • Lựa chọn phương thức hiển thị: Phần tử autovideosink tự động lựa chọn một phương thức hiển thị video phù hợp với hệ thống, chẳng hạn: ~ X11 trên hệ thống Linux. ~ DirectX hoặc Windows Media trên hệ thống Windows. ~ CoreVideo hoặc OpenGL trên macOS.
  • Hiển thị video: Sau khi chọn phương thức phù hợp, autovideosink sẽ truyền dữ liệu video (khung hình) vào hệ thống hiển thị. Nếu là video 2D, các khung hình sẽ được vẽ trực tiếp lên màn hình; nếu video 3D, phần tử có thể sử dụng OpenGL hoặc các API tương tự để hiển thị video dưới dạng đồ họa 3D.
  • Cơ chế đồng bộ: autovideosink có thể đồng bộ hóa video với các yếu tố khác trong pipeline, như âm thanh, để đảm bảo cả video và âm thanh được phát đúng thời gian.
  • Quá trình hoạt động:
  • Dữ liệu video (khung hình) được gửi qua autovideosink, và phần tử này sẽ xử lý để hiển thị video lên màn hình theo phương thức phù hợp. Nếu video có sự thay đổi về độ phân giải hoặc tỷ lệ khung hình, autovideosink có thể điều chỉnh tự động để khớp với màn hình và các tính năng của hệ thống.

Tóm tắt:

Đây là tóm tắt một số ý cơ bản của Gstreamer mình sẽ sớm tổng hợp thêm các phần tiếp theo của session này nha. Cảm ơn các bạn đã đọc bài nếu các bạn có câu hỏi nào hãy liên hệ qua gmail: vuquochuy073@gmail.com, mình rất vui nếu đó là các câu hỏi xây dựng cũng như củng cố thêm kiến thức cho cộng đồng AI Việt Nam.

Bình luận

Bài viết tương tự

- vừa được xem lúc

TorchServe, công cụ hỗ trợ triển khai mô hình PyTorch

Lời mở đầu. Hôm nay tôi sẽ giới thiệu sơ qua cho các bạn công cụ triển khai mô hình dành riêng cho mô hình PyTorch.

0 0 37

- vừa được xem lúc

Bacteria classification bằng thư viện fastai

Giới thiệu. fastai là 1 thư viện deep learning hiện đại, cung cấp API bậc cao để giúp các lập trình viên AI cài đặt các mô hình deep learning cho các bài toán như classification, segmentation... và nhanh chóng đạt được kết quả tốt chỉ bằng vài dòng code. Bên cạnh đó, nhờ được phát triển trên nền tản

0 0 37

- vừa được xem lúc

Pytorch - Một số tips hay, tối ưu cho quá trình huấn luyện model của bạn

Xin chào các bạn, cũng lâu rồi mình mới quay trở lại ngồi viết mấy bài chia sẻ trên viblo. Chẹp, dạo này làm remote nên lười vận động, lười cả viết bài hẳn.

0 0 276

- vừa được xem lúc

Hướng dẫn tất tần tật về Pytorch để làm các bài toán về AI

Giới thiệu về pytorch. Pytorch là framework được phát triển bởi Facebook.

0 0 181

- vừa được xem lúc

Nhận diện khuôn mặt với mạng MTCNN và FaceNet (Phần 2)

Chào mừng các bạn đã quay lại với series "Nhận diện khuôn mặt với mạng MTCNN và FaceNet" của mình. Ở phần 1, mình đã giải thích qua về lý thuyết và nền tảng của 2 mạng là MTCNN và FaceNet.

0 0 734

- vừa được xem lúc

Video Understanding: Tổng quan

"Thợ lặn" hơi lâu, sau sự kiện MayFest thì đến bây giờ cũng là 3 tháng rồi mình không viết thêm bài mới. Thế nên là, hôm nay mình lại ngoi lên, đầu tiên là để luyện lại văn viết một chút, tiếp theo cũ

0 0 97