Difference between revisions of "Best Practices"
Line 32: | Line 32: | ||
Choosing the correct texture format for your platform is very important. The simplest format to convert the video buffer to is RGB, but that format is rarely optimised for the texture. Fore example, DirectX prefers BGRX while OpenGL ES on iOS and ANDROID prefer RGBX. If you use any other format, when uploading pixel data, the display card has to first convert your pixels in it's native format, thus slowing down texture upload speed. So, be careful which format you choose as video decoding performance doesn't always have to be related to slow video decoding! | Choosing the correct texture format for your platform is very important. The simplest format to convert the video buffer to is RGB, but that format is rarely optimised for the texture. Fore example, DirectX prefers BGRX while OpenGL ES on iOS and ANDROID prefer RGBX. If you use any other format, when uploading pixel data, the display card has to first convert your pixels in it's native format, thus slowing down texture upload speed. So, be careful which format you choose as video decoding performance doesn't always have to be related to slow video decoding! | ||
+ | |||
+ | == Audio / Video sync == | ||
+ | |||
+ | Don't ever just play an audio file and a matching video file and expect them to stay in sync :) | ||
+ | The proper way to do A/V sync in libtheoraplayer is to either use the audio track embedded in the actual file or to provide your own file and use a TheoraTimer instance to control your video timer. | ||
+ | In the second case, it's best to use the current timestamp of the playing audio file as a time indicator for the video file. That way you're ensuring sync. | ||
+ | However, as we have been unpleasantly surprised, be weary of the following fact: Some audio API's don't give you a very precise audio timestamp! For example OpenAL on Android and iOS gives a very crude timestamp resulting in many frame drops as the timer doesn't progress continuously. | ||
+ | In this case, we recommend using a float or double timer variable that increases with time but to correct it with the audio timestamp, but not to override it when the timestamp changes but to slowly sync it over the next second or so, to avoid sudden movements. |
Revision as of 15:34, 25 November 2014
Before reading this page, make sure you've integrated libtheoraplayer in your app. More details on the Tutorial page.
Contents
Number of precached frames
When creating a TheoraVideoClip object, you can choose how many frames you'd like to "precache". Precaching means decoding frames in advance and storing them until they are ready to be displayed. This mechanism ensures smooth playback but it consumes memory. Because some frames take more time to decode than others, depending on how much of the picture has changed in between frames, you should always precache at least a few frames.
How much frames you should precache depends on many factors the most important of which are:
- How much memory your target device / platform has
- How fast is the CPU that decodes the video
- How much rapid movement your video has (quick changes in picture require more decoding time)
If you have a CPU or Theora is slow to decode on a given system, you can buff out complex frame decoding by increasing the number of precached frames. Fast CPU's generally don't require too much precaching because they can decode fast enough, but if you have many concurrent videos playing, then decoding performance can vary.
In our experience, you should precache 4-16 frames and make the decision dynamically based on 2 factors: how much RAM your device has and how many CPU cores (or hardware threads) you have available. The more RAM, the more precached frames you can afford, but on multi core CPU's decoding is faster.
Keep in mind that each precached frame takes a lot of RAM. For example, a 512x512 RGB video consumes 768kB, which means frame cache of 16 frames takes 12 MB. a 1080p video with a 16 frame cache would take 95 MB!
Videos in Games
If you're using libtheoraplayer for a game project and are using a 3D graphics API such as OpenGL or DirectX then there are many performance factors you have to be aware of.
Texture Swapping
Unlike primitive 2D graphics frameworks, modern display cards tend to parallelize everything. When you're done doing draw calls for one frame in OpenGL for instance, the device probably hasn't finished rendering the frame before you start with the next iteration. Because of this if you use one single texture to upload video frames and draw them, there could be performance issues. The texture you're now uploading video data could be currently in use for your previous display frame. Thus you'll have to wait untill the frame is drawn before you can upload the next video frame onto it. Therefore it is suggested that you use 2 textures to display video data, swapping their use each time you upload new video frame data.
Texture format
Choosing the correct texture format for your platform is very important. The simplest format to convert the video buffer to is RGB, but that format is rarely optimised for the texture. Fore example, DirectX prefers BGRX while OpenGL ES on iOS and ANDROID prefer RGBX. If you use any other format, when uploading pixel data, the display card has to first convert your pixels in it's native format, thus slowing down texture upload speed. So, be careful which format you choose as video decoding performance doesn't always have to be related to slow video decoding!
Audio / Video sync
Don't ever just play an audio file and a matching video file and expect them to stay in sync :) The proper way to do A/V sync in libtheoraplayer is to either use the audio track embedded in the actual file or to provide your own file and use a TheoraTimer instance to control your video timer. In the second case, it's best to use the current timestamp of the playing audio file as a time indicator for the video file. That way you're ensuring sync. However, as we have been unpleasantly surprised, be weary of the following fact: Some audio API's don't give you a very precise audio timestamp! For example OpenAL on Android and iOS gives a very crude timestamp resulting in many frame drops as the timer doesn't progress continuously. In this case, we recommend using a float or double timer variable that increases with time but to correct it with the audio timestamp, but not to override it when the timestamp changes but to slowly sync it over the next second or so, to avoid sudden movements.