Như vậy chúng ta đã biết cách play một video, sound nhưng điều đó chưa đử đẻ gọi là xử lý video (movie). Vì vậy phần này sẽ cung cấp thêm những kiến thức xử lý video đó là đồng bộ video (Synching Video).
1. DTS và PTS
Như chúng ta biết video là sự kết hợp của 2 thành phần chính là luồng hình ảnh(video streams) và luồng âm thanh(sound streams). Video là một chuỗi liên tiếp các frame được hiển thị một cách liên tục và tốc độ hiển thị các frame đó phụ thuộc vào thông tin của luồng video gọi là frame per second. Còn thông tin đặc trưng cho sound streams là sample rate. Vậy làm thế nào đẻ đồng bộ giữa âm thanh và hình ảnh sao cho khi chúng ta xem một đoạn video thì hình ảnh và âm thanh khớp nhau. Làm thế nào đẻ cho chương trình có thể biết được khi nào cần hiển thị một frame và thời gian hiện thị frame đó. Việc đồng bộ video không chỉ đơn giản là đếm(counting) các frames và nhân chúng với tốc độ frame( frame rate), điều này có thể dẫn đến trường hợp không đồng bộ giữa hình ảnh và âm thanh.
Trong FFMPEG thì packets nhận được từ stream chứ 2 giá trị DTS(decoding time stamp) và PTS(Presentation time stamp). Để hiểu được 2 giá trị này chúng ta cần phải biết cách movies được lưu trữ. Một vài định dạng, giống như MPEG thì có 3loại frame là B("bidirectional") , I("intra"), P("predicted"). I chứa full frame, P nội suy ra từ I nên nó dựa thông tin từ I. B frame giống P nhưng nó dựa vào thông tin được tìm tháy của cả I và P. Điều này cũng giải thích vì sao sẽ có thể không có finnished frame sau khi cúng ta gọi hàm avcodec_decode_video.
Giả sử chúng ta có một movie và các frame được hiển thị như sau: IBBP. Bây giờ chúng ta cần biết thông tin trong P trước khi chúng ta hiển thị B. Chính vì lý do này mà các frame sẽ được lưu trữ là IPBB. Và cũng chính vì điều này mà chúng ta cần pahir có DTS và PTs. DTS bảo cho chúng ta biết khi nào decode frame và PTS cho chúng ta biết khi nào cần hiển thị frame đó. Bởi vậy trong trường hợp này thì luống stream của chúng ta nhìn sẽ như thế này:
PTS và DTS khác nhau khi stream được hiển thị có B frame trong đó.
Khi chúng ta sử dụng hàm av_read_frame để nhận một packet từ luồng stream. Thì giá trị PTS và DTS sễ được chứa trong packet đó, nhưng chúng ta đang thực sự muốn PTS của raw frame mới được decode ra để chúng ta có thẻ biết khi nào hiển thị frame đó. Tuy nhiên struct AVFrame nhận được từ hàm avcodec_decode_video sẽ không cho chúng ta được giá trị PTS hữu ích mà chúng ta cần mặc dù nó có chứa tham số PTS. Rất may là ffmpeg sắp xếp lại Packet(reoders the packet) khi chúng decode bởi vậy DTS của packet đang được sử lý bởi hàm avcodec_decode_video sẽ là PTS của frame mà nó trả về nhưng không phải lúc nào ta cũng nhận được tông tin này. Vậy làm thẻ nào đẻ tìm được PTS chúng ta cần?
Có một cách đẻ tìm PTS của Frame. Chúng ta save PTS của Packet đầu tiên của một frame: nó sẽ là PTS của finished frame. Bời vậy khi frame không có DTS, chúng ta sẽ điều chỉnh điều này để save PTS. Chúng ta sẽ tìm ra packet nào là packet đầu tiên của một frame như sau: Mõi khi packet bắt đầu một frame, hàm avcodec_decode_video sẽ gọi một function đẻ cấp phát một buffer trong frame của chúng ta. Và tất nhiên FFMPEG sẽ cho phép chúng ta định nghĩ lại hàm cấp phát đó.
2. Synching
Idea: Sau khi show một frame, chúng ta tìm ra khi nào next frame sẽ nên được show. Sau đó chúng ta sẽ set một new timeout đẻ refresh video lại sau khi một khoảng thời gian. Chúng ta sẽ check giá trị PTS của next frame đói với clock hệ thống(system clock) để biết được timeout sẽ là bao nhiêu. Đó là ý tưởng như sẽ có 2 vấn đề cần thực hiện:
Đầu tiên là vấn đề biết được next PTS. Bạm vó thẻ nghĩ là có thể thêm video rate vào PTS hiện tại và suy nghĩ đó là đúng. Tuy nhiên có một vài loại video mà frame sẽ được hiện thị lặp lại. Có nghĩa là chuungs ta sẽ repeat frame hiện tại một thời gian ngàu nhiên. Chính là nguyên nhân làm cho next frame hiển thị sớm hơn. Bởi vậy chúng ta càn tính toán cho điều này.