mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-14 02:27:39 -04:00
Simplify mpegplayer a bit and use array-based lists rather than linked lists for stream management. Move a couple useful functions to handle pointer arrays from kernel.c into general.c; mpeglayer now makes use of them.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26101 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
9fde12676b
commit
fcf36dd4f9
15 changed files with 199 additions and 313 deletions
|
@ -724,6 +724,11 @@ static const struct plugin_api rockbox_api = {
|
|||
#ifdef AUDIOHW_HAVE_EQ
|
||||
sound_enum_hw_eq_band_setting,
|
||||
#endif
|
||||
|
||||
#if CONFIG_CODEC == SWCODEC
|
||||
find_array_ptr,
|
||||
remove_array_ptr,
|
||||
#endif
|
||||
};
|
||||
|
||||
int plugin_load(const char* plugin, const void* parameter)
|
||||
|
|
|
@ -142,7 +142,7 @@ void* plugin_get_buffer(size_t *buffer_size);
|
|||
#define PLUGIN_MAGIC 0x526F634B /* RocK */
|
||||
|
||||
/* increase this every time the api struct changes */
|
||||
#define PLUGIN_API_VERSION 185
|
||||
#define PLUGIN_API_VERSION 186
|
||||
|
||||
/* update this to latest version if a change to the api struct breaks
|
||||
backwards compatibility (and please take the opportunity to sort in any
|
||||
|
@ -889,6 +889,11 @@ int (*round_value_to_list32)(unsigned long value,
|
|||
int (*sound_enum_hw_eq_band_setting)(unsigned int band,
|
||||
unsigned int band_setting);
|
||||
#endif /* AUDIOHW_HAVE_EQ */
|
||||
|
||||
#if CONFIG_CODEC == SWCODEC
|
||||
void ** (*find_array_ptr)(void **arr, void *ptr);
|
||||
int (*remove_array_ptr)(void **arr, void *ptr);
|
||||
#endif
|
||||
};
|
||||
|
||||
/* plugin header */
|
||||
|
|
|
@ -29,6 +29,5 @@ disk_buf.c
|
|||
mpeg_settings.c
|
||||
stream_mgr.c
|
||||
mpegplayer.c
|
||||
mpeg_linkedlist.c
|
||||
mpeg_parser.c
|
||||
mpeg_misc.c
|
||||
|
|
|
@ -30,7 +30,7 @@ static struct queue_sender_list disk_buf_queue_send SHAREDBSS_ATTR;
|
|||
static uint32_t disk_buf_stack[DEFAULT_STACK_SIZE*2/sizeof(uint32_t)];
|
||||
|
||||
struct disk_buf disk_buf SHAREDBSS_ATTR;
|
||||
static struct list_item nf_list;
|
||||
static void *nf_list[MPEGPLAYER_MAX_STREAMS+1];
|
||||
|
||||
static inline void disk_buf_lock(void)
|
||||
{
|
||||
|
@ -45,13 +45,12 @@ static inline void disk_buf_unlock(void)
|
|||
static inline void disk_buf_on_clear_data_notify(struct stream_hdr *sh)
|
||||
{
|
||||
DEBUGF("DISK_BUF_CLEAR_DATA_NOTIFY: 0x%02X (cleared)\n",
|
||||
STR_FROM_HEADER(sh)->id);
|
||||
list_remove_item(&sh->nf);
|
||||
STR_FROM_HDR(sh)->id);
|
||||
list_remove_item(nf_list, sh);
|
||||
}
|
||||
|
||||
|
||||
inline bool disk_buf_is_data_ready(struct stream_hdr *sh,
|
||||
ssize_t margin)
|
||||
ssize_t margin)
|
||||
{
|
||||
/* Data window available? */
|
||||
off_t right = sh->win_right;
|
||||
|
@ -71,7 +70,7 @@ void dbuf_l2_init(struct dbuf_l2_cache *l2_p)
|
|||
|
||||
static int disk_buf_on_data_notify(struct stream_hdr *sh)
|
||||
{
|
||||
DEBUGF("DISK_BUF_DATA_NOTIFY: 0x%02X ", STR_FROM_HEADER(sh)->id);
|
||||
DEBUGF("DISK_BUF_DATA_NOTIFY: 0x%02X ", STR_FROM_HDR(sh)->id);
|
||||
|
||||
if (sh->win_left <= sh->win_right)
|
||||
{
|
||||
|
@ -85,7 +84,7 @@ static int disk_buf_on_data_notify(struct stream_hdr *sh)
|
|||
sh->win_left, sh->win_right,
|
||||
disk_buf.win_left, disk_buf.win_right);
|
||||
/* Be sure it's not listed though if multiple requests were made */
|
||||
list_remove_item(&sh->nf);
|
||||
list_remove_item(nf_list, sh);
|
||||
return DISK_BUF_NOTIFY_OK;
|
||||
}
|
||||
|
||||
|
@ -95,7 +94,7 @@ static int disk_buf_on_data_notify(struct stream_hdr *sh)
|
|||
case TSTATE_BUFFERING:
|
||||
case TSTATE_INIT:
|
||||
disk_buf.state = TSTATE_BUFFERING;
|
||||
list_add_item(&nf_list, &sh->nf);
|
||||
list_add_item(nf_list, sh);
|
||||
DEBUGF("(registered)\n"
|
||||
" swl:%lu swr:%lu\n"
|
||||
" dwl:%lu dwr:%lu\n",
|
||||
|
@ -109,20 +108,17 @@ static int disk_buf_on_data_notify(struct stream_hdr *sh)
|
|||
return DISK_BUF_NOTIFY_ERROR;
|
||||
}
|
||||
|
||||
static bool check_data_notifies_callback(struct list_item *item,
|
||||
intptr_t data)
|
||||
static bool check_data_notifies_callback(struct stream_hdr *sh, intptr_t data)
|
||||
{
|
||||
struct stream_hdr *sh = TYPE_FROM_MEMBER(struct stream_hdr, item, nf);
|
||||
|
||||
if (disk_buf_is_data_ready(sh, 0))
|
||||
{
|
||||
/* Remove from list then post notification - post because send
|
||||
* could result in a wait for each thread to finish resulting
|
||||
* in deadlock */
|
||||
list_remove_item(item);
|
||||
str_post_msg(STR_FROM_HEADER(sh), DISK_BUF_DATA_NOTIFY, 0);
|
||||
list_remove_item(nf_list, sh);
|
||||
str_post_msg(STR_FROM_HDR(sh), DISK_BUF_DATA_NOTIFY, 0);
|
||||
DEBUGF("DISK_BUF_DATA_NOTIFY: 0x%02X (notified)\n",
|
||||
STR_FROM_HEADER(sh)->id);
|
||||
STR_FROM_HDR(sh)->id);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -130,15 +126,17 @@ static bool check_data_notifies_callback(struct list_item *item,
|
|||
}
|
||||
|
||||
/* Check registered streams and notify them if their data is available */
|
||||
static void check_data_notifies(void)
|
||||
static inline void check_data_notifies(void)
|
||||
{
|
||||
list_enum_items(&nf_list, check_data_notifies_callback, 0);
|
||||
list_enum_items(nf_list,
|
||||
(list_enum_callback_t)check_data_notifies_callback,
|
||||
0);
|
||||
}
|
||||
|
||||
/* Clear all registered notifications - do not post them */
|
||||
static inline void clear_data_notifies(void)
|
||||
{
|
||||
list_clear_all(&nf_list);
|
||||
list_clear_all(nf_list);
|
||||
}
|
||||
|
||||
/* Background buffering when streaming */
|
||||
|
@ -492,7 +490,7 @@ static void disk_buf_thread(void)
|
|||
disk_buf_buffer();
|
||||
|
||||
/* Check for any due notifications if any are pending */
|
||||
if (nf_list.next != NULL)
|
||||
if (*nf_list != NULL)
|
||||
check_data_notifies();
|
||||
|
||||
/* Still more data left? */
|
||||
|
@ -915,7 +913,6 @@ void disk_buf_reply_msg(intptr_t retval)
|
|||
bool disk_buf_init(void)
|
||||
{
|
||||
disk_buf.thread = 0;
|
||||
list_initialize(&nf_list);
|
||||
|
||||
rb->mutex_init(&disk_buf_mtx);
|
||||
|
||||
|
|
|
@ -1,151 +0,0 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Linked list API definitions
|
||||
*
|
||||
* Copyright (c) 2007 Michael Sevakis
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "plugin.h"
|
||||
#include "mpegplayer.h"
|
||||
#include "mpeg_linkedlist.h"
|
||||
|
||||
/* Initialize a master list head */
|
||||
void list_initialize(struct list_item *master_list_head)
|
||||
{
|
||||
master_list_head->prev = master_list_head->next = NULL;
|
||||
}
|
||||
|
||||
/* Are there items after the head item? */
|
||||
bool list_is_empty(struct list_item *head_item)
|
||||
{
|
||||
return head_item->next == NULL;
|
||||
}
|
||||
|
||||
/* Does the item belong to a list? */
|
||||
bool list_is_item_listed(struct list_item *item)
|
||||
{
|
||||
return item->prev != NULL;
|
||||
}
|
||||
|
||||
/* Is the item a member in a particular list? */
|
||||
bool list_is_member(struct list_item *master_list_head,
|
||||
struct list_item *item)
|
||||
{
|
||||
if (item != master_list_head && item->prev != NULL)
|
||||
{
|
||||
struct list_item *curr = master_list_head->next;
|
||||
|
||||
while (curr != NULL)
|
||||
{
|
||||
if (item != curr)
|
||||
{
|
||||
curr = curr->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Remove an item from a list - no head item needed */
|
||||
void list_remove_item(struct list_item *item)
|
||||
{
|
||||
if (item->prev == NULL)
|
||||
{
|
||||
/* Not in a list - no change - could be the master list head
|
||||
* as well which cannot be removed */
|
||||
return;
|
||||
}
|
||||
|
||||
item->prev->next = item->next;
|
||||
|
||||
if (item->next != NULL)
|
||||
{
|
||||
/* Not last item */
|
||||
item->next->prev = item->prev;
|
||||
}
|
||||
|
||||
/* Mark as not in a list */
|
||||
item->prev = NULL;
|
||||
}
|
||||
|
||||
/* Add a list item after the base item */
|
||||
void list_add_item(struct list_item *head_item,
|
||||
struct list_item *item)
|
||||
{
|
||||
if (item->prev != NULL)
|
||||
{
|
||||
/* Already in a list - no change */
|
||||
DEBUGF("list_add_item: item already in a list\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (item == head_item)
|
||||
{
|
||||
/* Cannot add the item to itself */
|
||||
DEBUGF("list_add_item: item == head_item\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Insert first */
|
||||
item->prev = head_item;
|
||||
item->next = head_item->next;
|
||||
|
||||
if (head_item->next != NULL)
|
||||
{
|
||||
/* Not first item */
|
||||
head_item->next->prev = item;
|
||||
}
|
||||
|
||||
head_item->next = item;
|
||||
}
|
||||
|
||||
/* Clear list items after the head item */
|
||||
void list_clear_all(struct list_item *head_item)
|
||||
{
|
||||
struct list_item *curr = head_item->next;
|
||||
|
||||
while (curr != NULL)
|
||||
{
|
||||
list_remove_item(curr);
|
||||
curr = head_item->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enumerate all items after the head item - passing each item in turn
|
||||
* to the callback as well as the data value. The current item may be
|
||||
* safely removed. Items added after the current position will be enumated
|
||||
* but not ones added before it. The callback may return false to stop
|
||||
* the enumeration. */
|
||||
void list_enum_items(struct list_item *head_item,
|
||||
list_enum_callback_t callback,
|
||||
intptr_t data)
|
||||
{
|
||||
struct list_item *next = head_item->next;
|
||||
|
||||
while (next != NULL)
|
||||
{
|
||||
struct list_item *curr = next;
|
||||
next = curr->next;
|
||||
if (!callback(curr, data))
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Linked list API declarations
|
||||
*
|
||||
* Copyright (c) 2007 Michael Sevakis
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef MPEG_LINKEDLIST_H
|
||||
#define MPEG_LINKEDLIST_H
|
||||
|
||||
struct list_item
|
||||
{
|
||||
struct list_item *prev; /* previous item in list */
|
||||
struct list_item *next; /* next item in list */
|
||||
};
|
||||
|
||||
/* Utility macros to help get the actual structure pointer back */
|
||||
#define OFFSETOF(type, membername) ((off_t)&((type *)0)->membername)
|
||||
#define TYPE_FROM_MEMBER(type, memberptr, membername) \
|
||||
((type *)((intptr_t)(memberptr) - OFFSETOF(type, membername)))
|
||||
|
||||
/* Initialize a master list head */
|
||||
void list_initialize(struct list_item *master_list_head);
|
||||
|
||||
/* Are there items after the head item? */
|
||||
bool list_is_empty(struct list_item *head_item);
|
||||
|
||||
/* Does the item belong to a list? */
|
||||
bool list_is_item_listed(struct list_item *item);
|
||||
|
||||
/* Is the item a member in a particular list? */
|
||||
bool list_is_member(struct list_item *master_list_head,
|
||||
struct list_item *item);
|
||||
|
||||
/* Remove an item from a list - no head item needed */
|
||||
void list_remove_item(struct list_item *item);
|
||||
|
||||
/* Add a list item after the base item */
|
||||
void list_add_item(struct list_item *head_item,
|
||||
struct list_item *item);
|
||||
|
||||
/* Clear list items after the head item */
|
||||
void list_clear_all(struct list_item *head_item);
|
||||
|
||||
/* Enumerate all items after the head item - passing each item in turn
|
||||
* to the callback as well as the data value. The current item may be
|
||||
* safely removed. Items added after the current position will be enumated
|
||||
* but not ones added before it. The callback may return false to stop
|
||||
* the enumeration. */
|
||||
typedef bool (*list_enum_callback_t)(struct list_item *item, intptr_t data);
|
||||
|
||||
void list_enum_items(struct list_item *head_item,
|
||||
list_enum_callback_t callback,
|
||||
intptr_t data);
|
||||
|
||||
#endif /* MPEG_LINKEDLIST_H */
|
|
@ -102,3 +102,63 @@ uint32_t muldiv_uint32(uint32_t multiplicand,
|
|||
|
||||
return UINT32_MAX; /* Saturate */
|
||||
}
|
||||
|
||||
|
||||
/** Lists **/
|
||||
|
||||
/* Does the list have any members? */
|
||||
bool list_is_empty(void **list)
|
||||
{
|
||||
return *list == NULL;
|
||||
}
|
||||
|
||||
/* Is the item inserted into a particular list? */
|
||||
bool list_is_member(void **list, void *item)
|
||||
{
|
||||
return *rb->find_array_ptr(list, item) != NULL;
|
||||
}
|
||||
|
||||
/* Removes an item from a list - returns true if item was found
|
||||
* and thus removed. */
|
||||
bool list_remove_item(void **list, void *item)
|
||||
{
|
||||
return rb->remove_array_ptr(list, item) != -1;
|
||||
}
|
||||
|
||||
/* Adds a list item, insert last, if not already present. */
|
||||
void list_add_item(void **list, void *item)
|
||||
{
|
||||
void **item_p = rb->find_array_ptr(list, item);
|
||||
if (*item_p == NULL)
|
||||
*item_p = item;
|
||||
}
|
||||
|
||||
/* Clears the entire list. */
|
||||
void list_clear_all(void **list)
|
||||
{
|
||||
while (*list != NULL)
|
||||
*list++ = NULL;
|
||||
}
|
||||
|
||||
/* Enumerate all items in the array, passing each item in turn to the
|
||||
* callback as well as the data value. The current item may be safely
|
||||
* removed. Other changes during enumeration are undefined. The callback
|
||||
* may return 'false' to stop the enumeration early. */
|
||||
void list_enum_items(void **list,
|
||||
list_enum_callback_t callback,
|
||||
intptr_t data)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
void *item = *list;
|
||||
|
||||
if (item == NULL)
|
||||
break;
|
||||
|
||||
if (callback != NULL && !callback(item, data))
|
||||
break;
|
||||
|
||||
if (*list == item)
|
||||
list++; /* Item still there */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -202,4 +202,30 @@ uint32_t muldiv_uint32(uint32_t multiplicand,
|
|||
uint32_t multiplier,
|
||||
uint32_t divisor);
|
||||
|
||||
|
||||
/** Lists **/
|
||||
|
||||
/* Does the list have any members? */
|
||||
bool list_is_empty(void **list);
|
||||
|
||||
/* Is the item inserted into a particular list? */
|
||||
bool list_is_member(void **list, void *item);
|
||||
|
||||
/* Removes an item from a list - returns true if item was found
|
||||
* and thus removed. */
|
||||
bool list_remove_item(void **list, void *item);
|
||||
|
||||
/* Adds a list item, insert last, if not already present. */
|
||||
void list_add_item(void **list, void *item);
|
||||
|
||||
/* Clears the entire list. */
|
||||
void list_clear_all(void **list);
|
||||
|
||||
/* Enumerate all items in the array. */
|
||||
typedef bool (*list_enum_callback_t)(void *item, intptr_t data);
|
||||
|
||||
void list_enum_items(void **list,
|
||||
list_enum_callback_t callback,
|
||||
intptr_t data);
|
||||
|
||||
#endif /* MPEG_MISC_H */
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
#endif
|
||||
/* #else function-like empty macros are defined in the headers */
|
||||
|
||||
/* Should be enough for now */
|
||||
#define MPEGPLAYER_MAX_STREAMS 4
|
||||
|
||||
/* Memory allotments for various subsystems */
|
||||
#define MIN_MEMMARGIN (4*1024)
|
||||
|
||||
|
@ -85,7 +88,6 @@
|
|||
#include "mpeg2.h"
|
||||
#include "video_out.h"
|
||||
#include "mpeg_stream.h"
|
||||
#include "mpeg_linkedlist.h"
|
||||
#include "mpeg_misc.h"
|
||||
#include "mpeg_alloc.h"
|
||||
#include "stream_thread.h"
|
||||
|
|
|
@ -148,21 +148,21 @@ void stream_add_stream(struct stream *str)
|
|||
{
|
||||
actl_lock();
|
||||
|
||||
list_remove_item(&str->l);
|
||||
list_add_item(&stream_mgr.strl, &str->l);
|
||||
list_remove_item(stream_mgr.strl, str);
|
||||
list_add_item(stream_mgr.strl, str);
|
||||
|
||||
actl_unlock();
|
||||
}
|
||||
|
||||
/* Callback for various list-moving operations */
|
||||
static bool strl_enum_callback(struct list_item *item, intptr_t data)
|
||||
static bool strl_enum_callback(struct stream *str, intptr_t data)
|
||||
{
|
||||
actl_lock();
|
||||
|
||||
list_remove_item(item);
|
||||
list_remove_item(stream_mgr.strl, str);
|
||||
|
||||
if (data == 1)
|
||||
list_add_item(&stream_mgr.actl, item);
|
||||
list_add_item(stream_mgr.actl, str);
|
||||
|
||||
actl_unlock();
|
||||
|
||||
|
@ -172,38 +172,38 @@ static bool strl_enum_callback(struct list_item *item, intptr_t data)
|
|||
/* Clear all streams from active and playback pools */
|
||||
void stream_remove_streams(void)
|
||||
{
|
||||
list_enum_items(&stream_mgr.strl, strl_enum_callback, 0);
|
||||
list_enum_items(stream_mgr.strl,
|
||||
(list_enum_callback_t)strl_enum_callback, 0);
|
||||
}
|
||||
|
||||
/* Move the playback pool to the active list */
|
||||
void move_strl_to_actl(void)
|
||||
{
|
||||
list_enum_items(&stream_mgr.strl, strl_enum_callback, 1);
|
||||
list_enum_items(stream_mgr.strl,
|
||||
(list_enum_callback_t)strl_enum_callback, 1);
|
||||
}
|
||||
|
||||
/* Remove a stream from the active list and return it to the pool */
|
||||
static bool actl_stream_remove(struct stream *str)
|
||||
{
|
||||
if (list_is_member(&stream_mgr.actl, &str->l))
|
||||
{
|
||||
actl_lock();
|
||||
bool retval;
|
||||
|
||||
list_remove_item(&str->l);
|
||||
list_add_item(&stream_mgr.strl, &str->l);
|
||||
actl_lock();
|
||||
|
||||
actl_unlock();
|
||||
return true;
|
||||
}
|
||||
retval = list_remove_item(stream_mgr.actl, str);
|
||||
|
||||
return false;
|
||||
if (retval)
|
||||
list_add_item(stream_mgr.strl, str);
|
||||
|
||||
actl_unlock();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Broadcast a message to all active streams */
|
||||
static bool actl_stream_broadcast_callback(struct list_item *item,
|
||||
static bool actl_stream_broadcast_callback(struct stream *str,
|
||||
struct str_broadcast_data *sbd)
|
||||
{
|
||||
struct stream *str = TYPE_FROM_MEMBER(struct stream, item, l);
|
||||
|
||||
switch (sbd->cmd)
|
||||
{
|
||||
case STREAM_PLAY:
|
||||
|
@ -215,8 +215,8 @@ static bool actl_stream_broadcast_callback(struct list_item *item,
|
|||
{
|
||||
actl_lock();
|
||||
|
||||
list_remove_item(item);
|
||||
list_add_item(&stream_mgr.strl, item);
|
||||
list_remove_item(stream_mgr.actl, str);
|
||||
list_add_item(stream_mgr.strl, str);
|
||||
|
||||
actl_unlock();
|
||||
sbd->data = 0;
|
||||
|
@ -236,7 +236,7 @@ static void actl_stream_broadcast(int cmd, intptr_t data)
|
|||
struct str_broadcast_data sbd;
|
||||
sbd.cmd = cmd;
|
||||
sbd.data = data;
|
||||
list_enum_items(&stream_mgr.actl,
|
||||
list_enum_items(stream_mgr.actl,
|
||||
(list_enum_callback_t)actl_stream_broadcast_callback,
|
||||
(intptr_t)&sbd);
|
||||
}
|
||||
|
@ -623,7 +623,7 @@ static void stream_on_ev_complete(struct stream *str)
|
|||
{
|
||||
/* No - remove this stream from the active list */
|
||||
DEBUGF(" finished: 0x%02x\n", str->id);
|
||||
if (list_is_empty(&stream_mgr.actl))
|
||||
if (list_is_empty(stream_mgr.actl))
|
||||
{
|
||||
/* All streams have acked - stop playback */
|
||||
stream_on_stop(false);
|
||||
|
@ -820,10 +820,9 @@ void stream_wait_status(void)
|
|||
|
||||
/* Returns the smallest file window that includes all active streams'
|
||||
* windows */
|
||||
static bool stream_get_window_callback(struct list_item *item,
|
||||
static bool stream_get_window_callback(struct stream *str,
|
||||
struct stream_window *sw)
|
||||
{
|
||||
struct stream *str = TYPE_FROM_MEMBER(struct stream, item, l);
|
||||
off_t swl = str->hdr.win_left;
|
||||
off_t swr = str->hdr.win_right;
|
||||
|
||||
|
@ -845,7 +844,7 @@ bool stream_get_window(struct stream_window *sw)
|
|||
sw->right = LONG_MIN;
|
||||
|
||||
actl_lock();
|
||||
list_enum_items(&stream_mgr.actl,
|
||||
list_enum_items(stream_mgr.actl,
|
||||
(list_enum_callback_t)stream_get_window_callback,
|
||||
(intptr_t)sw);
|
||||
actl_unlock();
|
||||
|
@ -981,7 +980,6 @@ int stream_init(void)
|
|||
|
||||
stream_mgr.status = STREAM_STOPPED;
|
||||
stream_mgr_init_state();
|
||||
list_initialize(&stream_mgr.actl);
|
||||
|
||||
/* Initialize our window to the outside world first */
|
||||
rb->mutex_init(&stream_mgr.str_mtx);
|
||||
|
|
|
@ -35,8 +35,8 @@ struct stream_mgr
|
|||
bool seeked; /* A seek happened and things must be
|
||||
resynced */
|
||||
int status; /* Current playback status */
|
||||
struct list_item strl; /* List of available streams */
|
||||
struct list_item actl; /* List of active streams */
|
||||
void *strl[MPEGPLAYER_MAX_STREAMS+1]; /* List of available streams */
|
||||
void *actl[MPEGPLAYER_MAX_STREAMS+1]; /* List of active streams */
|
||||
struct mutex str_mtx; /* Main stream manager mutex */
|
||||
struct mutex actl_mtx; /* Lock for current-streams list */
|
||||
union /* A place for reusable non-cacheable parameters */
|
||||
|
|
|
@ -39,7 +39,6 @@ struct stream_hdr
|
|||
off_t pos; /* Start/current position for random-access read */
|
||||
};
|
||||
off_t limit; /* Limit for random-access read */
|
||||
struct list_item nf; /* List for data notification */
|
||||
};
|
||||
|
||||
struct stream
|
||||
|
@ -48,8 +47,6 @@ struct stream
|
|||
unsigned int thread; /* Stream's thread */
|
||||
uint8_t* curr_packet; /* Current stream packet beginning */
|
||||
uint8_t* curr_packet_end; /* Current stream packet end */
|
||||
struct list_item l; /* List of streams - either reserve pool
|
||||
or active pool */
|
||||
int state; /* State machine parsing mode */
|
||||
uint32_t start_pts; /* First timestamp for stream */
|
||||
uint32_t end_pts; /* Last timestamp for stream */
|
||||
|
@ -58,6 +55,8 @@ struct stream
|
|||
unsigned id; /* Stream identifier */
|
||||
};
|
||||
|
||||
#define STR_FROM_HDR(sh) ((struct stream *)(sh))
|
||||
|
||||
/* Make sure there there is always enough data buffered ahead for
|
||||
* the worst possible case - regardless of whether a valid stream
|
||||
* would actually produce that */
|
||||
|
@ -145,8 +144,6 @@ enum stream_status
|
|||
STREAM_NOT_FOUND, /* Match not found */
|
||||
};
|
||||
|
||||
#define STR_FROM_HEADER(sh) ((struct stream *)(sh))
|
||||
|
||||
/* Clip time to range for a particular stream */
|
||||
static inline uint32_t clip_time(struct stream *str, uint32_t time)
|
||||
{
|
||||
|
|
|
@ -72,4 +72,19 @@ char *create_datetime_filename(char *buffer, const char *path,
|
|||
bool unique_time);
|
||||
#endif /* CONFIG_RTC */
|
||||
|
||||
/***
|
||||
** Compacted pointer lists
|
||||
**
|
||||
** N-length list requires N+1 elements to ensure NULL-termination.
|
||||
**/
|
||||
|
||||
/* Find a pointer in a pointer array. Returns the addess of the element if
|
||||
found or the address of the terminating NULL otherwise. This can be used
|
||||
to bounds check and add items. */
|
||||
void ** find_array_ptr(void **arr, void *ptr);
|
||||
|
||||
/* Remove a pointer from a pointer array if it exists. Compacts it so that
|
||||
no gaps exist. Returns 0 on success and -1 if the element wasn't found. */
|
||||
int remove_array_ptr(void **arr, void *ptr);
|
||||
|
||||
#endif /* GENERAL_H */
|
||||
|
|
|
@ -196,3 +196,40 @@ char *create_datetime_filename(char *buffer, const char *path,
|
|||
return buffer;
|
||||
}
|
||||
#endif /* CONFIG_RTC */
|
||||
|
||||
/***
|
||||
** Compacted pointer lists
|
||||
**
|
||||
** N-length list requires N+1 elements to ensure NULL-termination.
|
||||
**/
|
||||
|
||||
/* Find a pointer in a pointer array. Returns the addess of the element if
|
||||
* found or the address of the terminating NULL otherwise. This can be used
|
||||
* to bounds check and add items. */
|
||||
void ** find_array_ptr(void **arr, void *ptr)
|
||||
{
|
||||
void *curr;
|
||||
for (curr = *arr; curr != NULL && curr != ptr; curr = *(++arr));
|
||||
return arr;
|
||||
}
|
||||
|
||||
/* Remove a pointer from a pointer array if it exists. Compacts it so that
|
||||
* no gaps exist. Returns 0 on success and -1 if the element wasn't found. */
|
||||
int remove_array_ptr(void **arr, void *ptr)
|
||||
{
|
||||
void *curr;
|
||||
arr = find_array_ptr(arr, ptr);
|
||||
|
||||
if (*arr == NULL)
|
||||
return -1;
|
||||
|
||||
/* Found. Slide up following items. */
|
||||
do
|
||||
{
|
||||
void **arr1 = arr + 1;
|
||||
*arr++ = curr = *arr1;
|
||||
}
|
||||
while (curr != NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "system.h"
|
||||
#include "panic.h"
|
||||
#include "debug.h"
|
||||
#include "general.h"
|
||||
|
||||
/* Make this nonzero to enable more elaborate checks on objects */
|
||||
#if defined(DEBUG) || defined(SIMULATOR)
|
||||
|
@ -61,40 +62,6 @@ static struct
|
|||
IF_COP( struct corelock cl; )
|
||||
} all_queues SHAREDBSS_ATTR;
|
||||
|
||||
/****************************************************************************
|
||||
* Common utilities
|
||||
****************************************************************************/
|
||||
|
||||
/* Find a pointer in a pointer array. Returns the addess of the element if
|
||||
* found or the address of the terminating NULL otherwise. */
|
||||
static void ** find_array_ptr(void **arr, void *ptr)
|
||||
{
|
||||
void *curr;
|
||||
for(curr = *arr; curr != NULL && curr != ptr; curr = *(++arr));
|
||||
return arr;
|
||||
}
|
||||
|
||||
/* Remove a pointer from a pointer array if it exists. Compacts it so that
|
||||
* no gaps exist. Returns 0 on success and -1 if the element wasn't found. */
|
||||
static int remove_array_ptr(void **arr, void *ptr)
|
||||
{
|
||||
void *curr;
|
||||
arr = find_array_ptr(arr, ptr);
|
||||
|
||||
if(*arr == NULL)
|
||||
return -1;
|
||||
|
||||
/* Found. Slide up following items. */
|
||||
do
|
||||
{
|
||||
void **arr1 = arr + 1;
|
||||
*arr++ = curr = *arr1;
|
||||
}
|
||||
while(curr != NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Standard kernel stuff
|
||||
****************************************************************************/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue