Video File Playback
1. Overview
This section describes how to play video files on BK7258, including supported containers/codecs, key Kconfig options, the playback pipeline, and how to use the sample project.
For Video Player example projects, please refer to:
For API reference about Video Player, please refer to:
Two API layers are provided:
Engine API: single-file playback control (play/stop/pause/seek/ff/rewind, etc.)
Playlist API: playlist management, track switching, and play modes on top of Engine
2. Supported features
Containers: AVI, MP4 (enable parsers via Kconfig)
Video: MJPEG, H264 (depending on decoder support)
Audio: PCM, AAC, etc. (depending on decoder support)
Controls: play/stop/pause/resume, seek, fast forward/rewind, volume/mute (requires upper-layer callbacks)
Queries: media info (duration, file size, audio/video parameters)
4. Kconfig options
Player Kconfig:
ap/components/bk_video_player/Kconfig
Common options (partial list):
CONFIG_AVI_PLAYER: enable the player component
CONFIG_BK_VIDEO_PLAYER_ENABLE_AVI_PARSER: enable AVI container parser
CONFIG_BK_VIDEO_PLAYER_ENABLE_MP4_PARSER: enable MP4 container parser
CONFIG_BK_VIDEO_PLAYER_ENABLE_AAC_DECODER: enable AAC audio decoder
CONFIG_BK_VIDEO_PLAYER_ENABLE_HW_JPEG_DECODER: enable HW JPEG (MJPEG) video decoder
CONFIG_BK_VIDEO_PLAYER_ENABLE_SW_JPEG_DECODER: enable SW JPEG (MJPEG) video decoder
Threads and stack sizes (see Kconfig for defaults):
CONFIG_BK_VIDEO_PLAYER_VIDEO_PARSE_THREAD_STACK_SIZE (vp_video_parse)
CONFIG_BK_VIDEO_PLAYER_AUDIO_PARSE_THREAD_STACK_SIZE (vp_audio_parse)
CONFIG_BK_VIDEO_PLAYER_VIDEO_DECODE_THREAD_STACK_SIZE (video_decode)
CONFIG_BK_VIDEO_PLAYER_AUDIO_DECODE_THREAD_STACK_SIZE (audio_decode)
CONFIG_BK_VIDEO_PLAYER_EVENT_THREAD_STACK_SIZE (vp_evt)
Note
The pipeline includes demux, decode, display, and audio output. PSRAM and sufficient heap are recommended. For stutter, corruption, or A/V sync issues, try lowering resolution, reducing pipeline buffer counts, increasing key stack sizes, and reducing logging.
5. Typical playback pipeline
Typical video file playback pipeline (Video Player pipeline)
Container parser: reads encoded audio/video packets from file
Decoder: decodes packets into PCM audio or video frames
Output: - Video: deliver decoded frames via
video.decode_complete_cbfor display - Audio: deliver decoded audio viaaudio.decode_complete_cbfor audio output
Upper layer must provide buffer allocation/free callbacks for different pipeline stages.
6. Engine API flow
Typical Engine API flow:
Fill
bk_video_player_config_t: - audio/video pipeline buffer counts - audio/video buffer alloc/free callbacks - decode complete callbacks - optional: volume/mute control callbacks, playback finished callback, etc.bk_video_player_engine_new()Register parser/decoder:
bk_video_player_engine_register_*()- This must be done beforeplay. Otherwise there is no available container parser/decoder inside the player, and it cannot parse media or start playback. - Media probing (e.g.get_media_info/ CLIinfo) also depends on registered container parsers. Without parsers, the player cannot probe or parse the file.bk_video_player_engine_open()bk_video_player_engine_set_file_path()bk_video_player_engine_play()Control with stop/pause/seek/ff/rewind as needed
bk_video_player_engine_close()bk_video_player_engine_delete()
Important
bk_video_player_engine_set_volume()requiresaudio_set_volume_cb, otherwise it returns an unsupported error.The playback finished callback is invoked asynchronously. Do not block for a long time inside it.
7. Playlist API flow
Playlist adds file list management and play mode:
bk_video_player_playlist_new()bk_video_player_playlist_open()Add files via
bk_video_player_playlist_add_file()Control playback via
bk_video_player_playlist_play_file()/play_next()/play_prev()/ etc.Configure play mode via
bk_video_player_playlist_set_play_mode()(stop/repeat/loop)bk_video_player_playlist_close()+bk_video_player_playlist_delete()
8. Sample project
Project path:
projects/video_player_example
The project provides video_play_engine and video_play_playlist CLIs to validate the player pipeline.
9. Usage example (Engine)
The following example shows the basic Engine call sequence. In real projects, you typically integrate display and audio output modules in the callbacks.
#include "components/bk_video_player/bk_video_player_engine.h"
#include "bk_video_player_mp4_parser.h"
#include "bk_video_player_avi_parser.h"
#include "bk_video_player_hw_jpeg_decoder.h"
#include "bk_video_player_sw_jpeg_decoder.h"
#include "bk_video_player_aac_decoder.h"
static avdk_err_t audio_buf_alloc(void *user_data, video_player_buffer_t *buffer)
{
(void)user_data;
if (buffer == NULL) {
return AVDK_ERR_INVALID_PARAM;
}
buffer->data = os_malloc(buffer->length);
if (buffer->data == NULL) {
return AVDK_ERR_NO_MEMORY;
}
return AVDK_ERR_OK;
}
static void audio_buf_free(void *user_data, video_player_buffer_t *buffer)
{
(void)user_data;
if (buffer && buffer->data) {
os_free(buffer->data);
buffer->data = NULL;
}
}
static avdk_err_t video_buf_alloc(void *user_data, video_player_buffer_t *buffer)
{
(void)user_data;
if (buffer == NULL) {
return AVDK_ERR_INVALID_PARAM;
}
buffer->data = os_malloc(buffer->length);
if (buffer->data == NULL) {
return AVDK_ERR_NO_MEMORY;
}
return AVDK_ERR_OK;
}
static void video_buf_free(void *user_data, video_player_buffer_t *buffer)
{
(void)user_data;
if (buffer && buffer->data) {
os_free(buffer->data);
buffer->data = NULL;
}
}
static void on_audio_decoded(void *user_data, const video_player_audio_packet_meta_t *meta, video_player_buffer_t *buffer)
{
(void)user_data;
(void)meta;
// Send decoded PCM to audio output, then free the buffer.
audio_buf_free(NULL, buffer);
}
static void on_video_decoded(void *user_data, const video_player_video_frame_meta_t *meta, video_player_buffer_t *buffer)
{
(void)user_data;
(void)meta;
// Display the decoded frame, then free the buffer.
video_buf_free(NULL, buffer);
}
avdk_err_t video_file_playback_example(void)
{
bk_video_player_engine_handle_t engine = NULL;
bk_video_player_config_t cfg = {0};
avdk_err_t ret = AVDK_ERR_OK;
cfg.user_data = NULL;
cfg.audio.parser_to_decode_buffer_count = 4;
cfg.audio.decode_to_output_buffer_count = 4;
cfg.audio.buffer_alloc_cb = audio_buf_alloc;
cfg.audio.buffer_free_cb = audio_buf_free;
cfg.audio.decode_complete_cb = on_audio_decoded;
cfg.video.parser_to_decode_buffer_count = 4;
cfg.video.decode_to_output_buffer_count = 4;
cfg.video.buffer_alloc_cb = video_buf_alloc;
cfg.video.buffer_free_cb = video_buf_free;
cfg.video.decode_complete_cb = on_video_decoded;
cfg.video.output_format = PIXEL_FMT_YUYV;
ret = bk_video_player_engine_new(&engine, &cfg);
if (ret != AVDK_ERR_OK) {
return ret;
}
// Register parsers/decoders before media probing (info/get_media_info) or playback.
#if CONFIG_BK_VIDEO_PLAYER_ENABLE_MP4_PARSER
ret = bk_video_player_engine_register_container_parser(engine, bk_video_player_get_mp4_parser_ops());
if (ret != AVDK_ERR_OK) {
bk_video_player_engine_delete(engine);
return ret;
}
#endif
#if CONFIG_BK_VIDEO_PLAYER_ENABLE_AVI_PARSER
ret = bk_video_player_engine_register_container_parser(engine, bk_video_player_get_avi_parser_ops());
if (ret != AVDK_ERR_OK) {
bk_video_player_engine_delete(engine);
return ret;
}
#endif
#if CONFIG_BK_VIDEO_PLAYER_ENABLE_HW_JPEG_DECODER
ret = bk_video_player_engine_register_video_decoder(engine, bk_video_player_get_hw_jpeg_decoder_ops());
if (ret != AVDK_ERR_OK) {
bk_video_player_engine_delete(engine);
return ret;
}
#endif
#if CONFIG_BK_VIDEO_PLAYER_ENABLE_SW_JPEG_DECODER
ret = bk_video_player_engine_register_video_decoder(engine, bk_video_player_get_sw_jpeg_decoder_ops());
if (ret != AVDK_ERR_OK) {
bk_video_player_engine_delete(engine);
return ret;
}
#endif
#if CONFIG_BK_VIDEO_PLAYER_ENABLE_AAC_DECODER
ret = bk_video_player_engine_register_audio_decoder(engine, bk_video_player_get_aac_audio_decoder_ops());
if (ret != AVDK_ERR_OK) {
bk_video_player_engine_delete(engine);
return ret;
}
#endif
ret = bk_video_player_engine_open(engine);
if (ret != AVDK_ERR_OK) {
bk_video_player_engine_delete(engine);
return ret;
}
ret = bk_video_player_engine_set_file_path(engine, "/sd0/record.mp4");
if (ret == AVDK_ERR_OK) {
ret = bk_video_player_engine_play(engine);
}
// Stop playback when needed.
if (ret == AVDK_ERR_OK) {
(void)bk_video_player_engine_stop(engine);
}
(void)bk_video_player_engine_close(engine);
(void)bk_video_player_engine_delete(engine);
return ret;
}