forked from KolibriOS/kolibrios
Fplay: h264 hardware decoding and output.
git-svn-id: svn://kolibrios.org@6133 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
49e6d69320
commit
fc65c2518c
@ -417,4 +417,3 @@ exit_whith_error:
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,9 +26,6 @@ volatile enum player_state sound_state = STOP;
|
|||||||
|
|
||||||
uint32_t win_width, win_height;
|
uint32_t win_width, win_height;
|
||||||
|
|
||||||
|
|
||||||
AVFrame *pFrame;
|
|
||||||
|
|
||||||
int have_sound = 0;
|
int have_sound = 0;
|
||||||
|
|
||||||
uint8_t *decoder_buffer;
|
uint8_t *decoder_buffer;
|
||||||
@ -147,6 +144,15 @@ int main( int argc, char *argv[])
|
|||||||
printf("codec id %x name %s\n",vst.vCtx->codec_id, vst.vCodec->name);
|
printf("codec id %x name %s\n",vst.vCtx->codec_id, vst.vCodec->name);
|
||||||
printf("ctx->pix_fmt %d\n", vst.vCtx->pix_fmt);
|
printf("ctx->pix_fmt %d\n", vst.vCtx->pix_fmt);
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&vst.input_list);
|
||||||
|
INIT_LIST_HEAD(&vst.output_list);
|
||||||
|
mutex_init(&vst.q_video.lock);
|
||||||
|
mutex_init(&vst.q_audio.lock);
|
||||||
|
mutex_init(&vst.gpu_lock);
|
||||||
|
mutex_init(&vst.decoder_lock);
|
||||||
|
mutex_init(&vst.input_lock);
|
||||||
|
mutex_init(&vst.output_lock);
|
||||||
|
|
||||||
if(vst.vCodec == NULL)
|
if(vst.vCodec == NULL)
|
||||||
{
|
{
|
||||||
printf("Unsupported codec with id %d for input stream %d\n",
|
printf("Unsupported codec with id %d for input stream %d\n",
|
||||||
@ -166,10 +172,6 @@ int main( int argc, char *argv[])
|
|||||||
|
|
||||||
printf("ctx->pix_fmt %d\n", vst.vCtx->pix_fmt);
|
printf("ctx->pix_fmt %d\n", vst.vCtx->pix_fmt);
|
||||||
|
|
||||||
mutex_init(&vst.q_video.lock);
|
|
||||||
mutex_init(&vst.q_audio.lock);
|
|
||||||
mutex_init(&vst.gpu_lock);
|
|
||||||
|
|
||||||
if (vst.aCtx->channels > 0)
|
if (vst.aCtx->channels > 0)
|
||||||
vst.aCtx->request_channels = FFMIN(2, vst.aCtx->channels);
|
vst.aCtx->request_channels = FFMIN(2, vst.aCtx->channels);
|
||||||
else
|
else
|
||||||
@ -224,10 +226,9 @@ int main( int argc, char *argv[])
|
|||||||
if(!init_video(&vst))
|
if(!init_video(&vst))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
decoder(&vst);
|
mutex_lock_timeout(&vst.decoder_lock, 3000);
|
||||||
|
|
||||||
// Free the YUV frame
|
decoder(&vst);
|
||||||
av_free(pFrame);
|
|
||||||
|
|
||||||
|
|
||||||
//__asm__ __volatile__("int3");
|
//__asm__ __volatile__("int3");
|
||||||
@ -241,7 +242,7 @@ int main( int argc, char *argv[])
|
|||||||
|
|
||||||
mutex_destroy(&vst.q_video.lock);
|
mutex_destroy(&vst.q_video.lock);
|
||||||
mutex_destroy(&vst.q_audio.lock);
|
mutex_destroy(&vst.q_audio.lock);
|
||||||
|
mutex_destroy(&vst.decoder_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,8 +335,7 @@ void decoder(vst_t* vst)
|
|||||||
}
|
}
|
||||||
decode_video(vst);
|
decode_video(vst);
|
||||||
ret = decode_audio(vst->aCtx, &vst->q_audio);
|
ret = decode_audio(vst->aCtx, &vst->q_audio);
|
||||||
}while(astream.count < resampler_size*2 &&
|
}while(astream.count < resampler_size*2 && ret == 1);
|
||||||
ret == 1);
|
|
||||||
|
|
||||||
sound_state = PREPARE;
|
sound_state = PREPARE;
|
||||||
decoder_state = PLAY;
|
decoder_state = PLAY;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
#include <libsync.h>
|
#include <libsync.h>
|
||||||
#include "pixlib3.h"
|
#include <pixlib3.h>
|
||||||
|
#include "list.h"
|
||||||
|
|
||||||
#define BLACK_MAGIC_SOUND
|
#define BLACK_MAGIC_SOUND
|
||||||
#define BLACK_MAGIC_VIDEO
|
#define BLACK_MAGIC_VIDEO
|
||||||
@ -18,10 +19,15 @@ typedef struct vstate vst_t;
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
struct list_head list;
|
||||||
enum AVPixelFormat format;
|
enum AVPixelFormat format;
|
||||||
AVPicture picture;
|
AVPicture picture;
|
||||||
int planar;
|
planar_t* planar;
|
||||||
|
int is_hw_pic;
|
||||||
|
int index;
|
||||||
double pts;
|
double pts;
|
||||||
|
double pkt_pts;
|
||||||
|
double pkt_dts;
|
||||||
volatile int ready;
|
volatile int ready;
|
||||||
}vframe_t;
|
}vframe_t;
|
||||||
|
|
||||||
@ -53,7 +59,7 @@ struct render
|
|||||||
EMPTY, INIT }state;
|
EMPTY, INIT }state;
|
||||||
enum win_state win_state;
|
enum win_state win_state;
|
||||||
|
|
||||||
void (*draw)(render_t *render, AVPicture *picture);
|
void (*draw)(render_t *render, vframe_t *vframe);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum player_state
|
enum player_state
|
||||||
@ -105,6 +111,7 @@ typedef struct {
|
|||||||
int put_packet(queue_t *q, AVPacket *pkt);
|
int put_packet(queue_t *q, AVPacket *pkt);
|
||||||
int get_packet(queue_t *q, AVPacket *pkt);
|
int get_packet(queue_t *q, AVPacket *pkt);
|
||||||
|
|
||||||
|
#define HWDEC_NUM_SURFACES 16
|
||||||
struct vstate
|
struct vstate
|
||||||
{
|
{
|
||||||
AVFormatContext *fCtx; /* format context */
|
AVFormatContext *fCtx; /* format context */
|
||||||
@ -119,10 +126,14 @@ struct vstate
|
|||||||
queue_t q_audio; /* audio packets queue */
|
queue_t q_audio; /* audio packets queue */
|
||||||
|
|
||||||
mutex_t gpu_lock; /* gpu access lock. libdrm not yet thread safe :( */
|
mutex_t gpu_lock; /* gpu access lock. libdrm not yet thread safe :( */
|
||||||
|
mutex_t decoder_lock;
|
||||||
|
|
||||||
vframe_t vframe[4]; /* decoder workset */
|
mutex_t input_lock;
|
||||||
int vfx; /* index of decoded frame */
|
mutex_t output_lock;
|
||||||
int dfx; /* index of renderd frame */
|
struct list_head input_list;
|
||||||
|
struct list_head output_list;
|
||||||
|
|
||||||
|
vframe_t *decoder_frame;
|
||||||
void *hwCtx; /* hardware context */
|
void *hwCtx; /* hardware context */
|
||||||
int hwdec; /* hardware decoder */
|
int hwdec; /* hardware decoder */
|
||||||
};
|
};
|
||||||
@ -165,7 +176,7 @@ static inline void GetNotify(void *event)
|
|||||||
::"a"(68),"b"(14),"c"(event));
|
::"a"(68),"b"(14),"c"(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
void va_convert_picture(vst_t *vst, int width, int height, AVPicture *pic);
|
void va_create_planar(vst_t *vst, vframe_t *vframe);
|
||||||
|
|
||||||
int init_fontlib();
|
int init_fontlib();
|
||||||
char *get_moviefile();
|
char *get_moviefile();
|
||||||
|
579
contrib/media/fplay/list.h
Normal file
579
contrib/media/fplay/list.h
Normal file
@ -0,0 +1,579 @@
|
|||||||
|
#ifndef _LINUX_LIST_H
|
||||||
|
#define _LINUX_LIST_H
|
||||||
|
|
||||||
|
#define LIST_POISON1 ((void *) 0x80000000)
|
||||||
|
#define LIST_POISON2 ((void *) 0x80001000)
|
||||||
|
|
||||||
|
|
||||||
|
#define container_of(ptr, type, member) ({ \
|
||||||
|
const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \
|
||||||
|
(type *)( (char *)__mptr - __builtin_offsetof(type,member) );})
|
||||||
|
|
||||||
|
struct list_head
|
||||||
|
{
|
||||||
|
struct list_head *next;
|
||||||
|
struct list_head *prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simple doubly linked list implementation.
|
||||||
|
*
|
||||||
|
* Some of the internal functions ("__xxx") are useful when
|
||||||
|
* manipulating whole lists rather than single entries, as
|
||||||
|
* sometimes we already know the next/prev entries and we can
|
||||||
|
* generate better code by using them directly rather than
|
||||||
|
* using the generic single-entry routines.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||||
|
|
||||||
|
#define LIST_HEAD(name) \
|
||||||
|
struct list_head name = LIST_HEAD_INIT(name)
|
||||||
|
|
||||||
|
static inline void INIT_LIST_HEAD(struct list_head *list)
|
||||||
|
{
|
||||||
|
list->next = list;
|
||||||
|
list->prev = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void __list_add(struct list_head *new,
|
||||||
|
struct list_head *prev,
|
||||||
|
struct list_head *next)
|
||||||
|
{
|
||||||
|
next->prev = new;
|
||||||
|
new->next = next;
|
||||||
|
new->prev = prev;
|
||||||
|
prev->next = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_add - add a new entry
|
||||||
|
* @new: new entry to be added
|
||||||
|
* @head: list head to add it after
|
||||||
|
*
|
||||||
|
* Insert a new entry after the specified head.
|
||||||
|
* This is good for implementing stacks.
|
||||||
|
*/
|
||||||
|
static inline void list_add(struct list_head *new, struct list_head *head)
|
||||||
|
{
|
||||||
|
__list_add(new, head, head->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_add_tail - add a new entry
|
||||||
|
* @new: new entry to be added
|
||||||
|
* @head: list head to add it before
|
||||||
|
*
|
||||||
|
* Insert a new entry before the specified head.
|
||||||
|
* This is useful for implementing queues.
|
||||||
|
*/
|
||||||
|
static inline void list_add_tail(struct list_head *new, struct list_head *head)
|
||||||
|
{
|
||||||
|
__list_add(new, head->prev, head);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delete a list entry by making the prev/next entries
|
||||||
|
* point to each other.
|
||||||
|
*
|
||||||
|
* This is only for internal list manipulation where we know
|
||||||
|
* the prev/next entries already!
|
||||||
|
*/
|
||||||
|
static inline void __list_del(struct list_head * prev, struct list_head * next)
|
||||||
|
{
|
||||||
|
next->prev = prev;
|
||||||
|
prev->next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_del - deletes entry from list.
|
||||||
|
* @entry: the element to delete from the list.
|
||||||
|
* Note: list_empty() on entry does not return true after this, the entry is
|
||||||
|
* in an undefined state.
|
||||||
|
*/
|
||||||
|
static inline void __list_del_entry(struct list_head *entry)
|
||||||
|
{
|
||||||
|
__list_del(entry->prev, entry->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void list_del(struct list_head *entry)
|
||||||
|
{
|
||||||
|
__list_del(entry->prev, entry->next);
|
||||||
|
entry->next = LIST_POISON1;
|
||||||
|
entry->prev = LIST_POISON2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_replace - replace old entry by new one
|
||||||
|
* @old : the element to be replaced
|
||||||
|
* @new : the new element to insert
|
||||||
|
*
|
||||||
|
* If @old was empty, it will be overwritten.
|
||||||
|
*/
|
||||||
|
static inline void list_replace(struct list_head *old,
|
||||||
|
struct list_head *new)
|
||||||
|
{
|
||||||
|
new->next = old->next;
|
||||||
|
new->next->prev = new;
|
||||||
|
new->prev = old->prev;
|
||||||
|
new->prev->next = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void list_replace_init(struct list_head *old,
|
||||||
|
struct list_head *new)
|
||||||
|
{
|
||||||
|
list_replace(old, new);
|
||||||
|
INIT_LIST_HEAD(old);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_del_init - deletes entry from list and reinitialize it.
|
||||||
|
* @entry: the element to delete from the list.
|
||||||
|
*/
|
||||||
|
static inline void list_del_init(struct list_head *entry)
|
||||||
|
{
|
||||||
|
__list_del_entry(entry);
|
||||||
|
INIT_LIST_HEAD(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_move - delete from one list and add as another's head
|
||||||
|
* @list: the entry to move
|
||||||
|
* @head: the head that will precede our entry
|
||||||
|
*/
|
||||||
|
static inline void list_move(struct list_head *list, struct list_head *head)
|
||||||
|
{
|
||||||
|
__list_del_entry(list);
|
||||||
|
list_add(list, head);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_move_tail - delete from one list and add as another's tail
|
||||||
|
* @list: the entry to move
|
||||||
|
* @head: the head that will follow our entry
|
||||||
|
*/
|
||||||
|
static inline void list_move_tail(struct list_head *list,
|
||||||
|
struct list_head *head)
|
||||||
|
{
|
||||||
|
__list_del_entry(list);
|
||||||
|
list_add_tail(list, head);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_is_last - tests whether @list is the last entry in list @head
|
||||||
|
* @list: the entry to test
|
||||||
|
* @head: the head of the list
|
||||||
|
*/
|
||||||
|
static inline int list_is_last(const struct list_head *list,
|
||||||
|
const struct list_head *head)
|
||||||
|
{
|
||||||
|
return list->next == head;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_empty - tests whether a list is empty
|
||||||
|
* @head: the list to test.
|
||||||
|
*/
|
||||||
|
static inline int list_empty(const struct list_head *head)
|
||||||
|
{
|
||||||
|
return head->next == head;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_empty_careful - tests whether a list is empty and not being modified
|
||||||
|
* @head: the list to test
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* tests whether a list is empty _and_ checks that no other CPU might be
|
||||||
|
* in the process of modifying either member (next or prev)
|
||||||
|
*
|
||||||
|
* NOTE: using list_empty_careful() without synchronization
|
||||||
|
* can only be safe if the only activity that can happen
|
||||||
|
* to the list entry is list_del_init(). Eg. it cannot be used
|
||||||
|
* if another CPU could re-list_add() it.
|
||||||
|
*/
|
||||||
|
static inline int list_empty_careful(const struct list_head *head)
|
||||||
|
{
|
||||||
|
struct list_head *next = head->next;
|
||||||
|
return (next == head) && (next == head->prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_rotate_left - rotate the list to the left
|
||||||
|
* @head: the head of the list
|
||||||
|
*/
|
||||||
|
static inline void list_rotate_left(struct list_head *head)
|
||||||
|
{
|
||||||
|
struct list_head *first;
|
||||||
|
|
||||||
|
if (!list_empty(head)) {
|
||||||
|
first = head->next;
|
||||||
|
list_move_tail(first, head);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_is_singular - tests whether a list has just one entry.
|
||||||
|
* @head: the list to test.
|
||||||
|
*/
|
||||||
|
static inline int list_is_singular(const struct list_head *head)
|
||||||
|
{
|
||||||
|
return !list_empty(head) && (head->next == head->prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void __list_cut_position(struct list_head *list,
|
||||||
|
struct list_head *head, struct list_head *entry)
|
||||||
|
{
|
||||||
|
struct list_head *new_first = entry->next;
|
||||||
|
list->next = head->next;
|
||||||
|
list->next->prev = list;
|
||||||
|
list->prev = entry;
|
||||||
|
entry->next = list;
|
||||||
|
head->next = new_first;
|
||||||
|
new_first->prev = head;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_cut_position - cut a list into two
|
||||||
|
* @list: a new list to add all removed entries
|
||||||
|
* @head: a list with entries
|
||||||
|
* @entry: an entry within head, could be the head itself
|
||||||
|
* and if so we won't cut the list
|
||||||
|
*
|
||||||
|
* This helper moves the initial part of @head, up to and
|
||||||
|
* including @entry, from @head to @list. You should
|
||||||
|
* pass on @entry an element you know is on @head. @list
|
||||||
|
* should be an empty list or a list you do not care about
|
||||||
|
* losing its data.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static inline void list_cut_position(struct list_head *list,
|
||||||
|
struct list_head *head, struct list_head *entry)
|
||||||
|
{
|
||||||
|
if (list_empty(head))
|
||||||
|
return;
|
||||||
|
if (list_is_singular(head) &&
|
||||||
|
(head->next != entry && head != entry))
|
||||||
|
return;
|
||||||
|
if (entry == head)
|
||||||
|
INIT_LIST_HEAD(list);
|
||||||
|
else
|
||||||
|
__list_cut_position(list, head, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void __list_splice(const struct list_head *list,
|
||||||
|
struct list_head *prev,
|
||||||
|
struct list_head *next)
|
||||||
|
{
|
||||||
|
struct list_head *first = list->next;
|
||||||
|
struct list_head *last = list->prev;
|
||||||
|
|
||||||
|
first->prev = prev;
|
||||||
|
prev->next = first;
|
||||||
|
|
||||||
|
last->next = next;
|
||||||
|
next->prev = last;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_splice - join two lists, this is designed for stacks
|
||||||
|
* @list: the new list to add.
|
||||||
|
* @head: the place to add it in the first list.
|
||||||
|
*/
|
||||||
|
static inline void list_splice(const struct list_head *list,
|
||||||
|
struct list_head *head)
|
||||||
|
{
|
||||||
|
if (!list_empty(list))
|
||||||
|
__list_splice(list, head, head->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_splice_tail - join two lists, each list being a queue
|
||||||
|
* @list: the new list to add.
|
||||||
|
* @head: the place to add it in the first list.
|
||||||
|
*/
|
||||||
|
static inline void list_splice_tail(struct list_head *list,
|
||||||
|
struct list_head *head)
|
||||||
|
{
|
||||||
|
if (!list_empty(list))
|
||||||
|
__list_splice(list, head->prev, head);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_splice_init - join two lists and reinitialise the emptied list.
|
||||||
|
* @list: the new list to add.
|
||||||
|
* @head: the place to add it in the first list.
|
||||||
|
*
|
||||||
|
* The list at @list is reinitialised
|
||||||
|
*/
|
||||||
|
static inline void list_splice_init(struct list_head *list,
|
||||||
|
struct list_head *head)
|
||||||
|
{
|
||||||
|
if (!list_empty(list)) {
|
||||||
|
__list_splice(list, head, head->next);
|
||||||
|
INIT_LIST_HEAD(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_splice_tail_init - join two lists and reinitialise the emptied list
|
||||||
|
* @list: the new list to add.
|
||||||
|
* @head: the place to add it in the first list.
|
||||||
|
*
|
||||||
|
* Each of the lists is a queue.
|
||||||
|
* The list at @list is reinitialised
|
||||||
|
*/
|
||||||
|
static inline void list_splice_tail_init(struct list_head *list,
|
||||||
|
struct list_head *head)
|
||||||
|
{
|
||||||
|
if (!list_empty(list)) {
|
||||||
|
__list_splice(list, head->prev, head);
|
||||||
|
INIT_LIST_HEAD(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_entry - get the struct for this entry
|
||||||
|
* @ptr: the &struct list_head pointer.
|
||||||
|
* @type: the type of the struct this is embedded in.
|
||||||
|
* @member: the name of the list_head within the struct.
|
||||||
|
*/
|
||||||
|
#define list_entry(ptr, type, member) \
|
||||||
|
container_of(ptr, type, member)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_first_entry - get the first element from a list
|
||||||
|
* @ptr: the list head to take the element from.
|
||||||
|
* @type: the type of the struct this is embedded in.
|
||||||
|
* @member: the name of the list_head within the struct.
|
||||||
|
*
|
||||||
|
* Note, that list is expected to be not empty.
|
||||||
|
*/
|
||||||
|
#define list_first_entry(ptr, type, member) \
|
||||||
|
list_entry((ptr)->next, type, member)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_last_entry - get the last element from a list
|
||||||
|
* @ptr: the list head to take the element from.
|
||||||
|
* @type: the type of the struct this is embedded in.
|
||||||
|
* @member: the name of the list_head within the struct.
|
||||||
|
*
|
||||||
|
* Note, that list is expected to be not empty.
|
||||||
|
*/
|
||||||
|
#define list_last_entry(ptr, type, member) \
|
||||||
|
list_entry((ptr)->prev, type, member)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_first_entry_or_null - get the first element from a list
|
||||||
|
* @ptr: the list head to take the element from.
|
||||||
|
* @type: the type of the struct this is embedded in.
|
||||||
|
* @member: the name of the list_head within the struct.
|
||||||
|
*
|
||||||
|
* Note that if the list is empty, it returns NULL.
|
||||||
|
*/
|
||||||
|
#define list_first_entry_or_null(ptr, type, member) \
|
||||||
|
(!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_next_entry - get the next element in list
|
||||||
|
* @pos: the type * to cursor
|
||||||
|
* @member: the name of the list_head within the struct.
|
||||||
|
*/
|
||||||
|
#define list_next_entry(pos, member) \
|
||||||
|
list_entry((pos)->member.next, __typeof__(*(pos)), member)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_prev_entry - get the prev element in list
|
||||||
|
* @pos: the type * to cursor
|
||||||
|
* @member: the name of the list_head within the struct.
|
||||||
|
*/
|
||||||
|
#define list_prev_entry(pos, member) \
|
||||||
|
list_entry((pos)->member.prev, __typeof__(*(pos)), member)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each - iterate over a list
|
||||||
|
* @pos: the &struct list_head to use as a loop cursor.
|
||||||
|
* @head: the head for your list.
|
||||||
|
*/
|
||||||
|
#define list_for_each(pos, head) \
|
||||||
|
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_prev - iterate over a list backwards
|
||||||
|
* @pos: the &struct list_head to use as a loop cursor.
|
||||||
|
* @head: the head for your list.
|
||||||
|
*/
|
||||||
|
#define list_for_each_prev(pos, head) \
|
||||||
|
for (pos = (head)->prev; pos != (head); pos = pos->prev)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_safe - iterate over a list safe against removal of list entry
|
||||||
|
* @pos: the &struct list_head to use as a loop cursor.
|
||||||
|
* @n: another &struct list_head to use as temporary storage
|
||||||
|
* @head: the head for your list.
|
||||||
|
*/
|
||||||
|
#define list_for_each_safe(pos, n, head) \
|
||||||
|
for (pos = (head)->next, n = pos->next; pos != (head); \
|
||||||
|
pos = n, n = pos->next)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
|
||||||
|
* @pos: the &struct list_head to use as a loop cursor.
|
||||||
|
* @n: another &struct list_head to use as temporary storage
|
||||||
|
* @head: the head for your list.
|
||||||
|
*/
|
||||||
|
#define list_for_each_prev_safe(pos, n, head) \
|
||||||
|
for (pos = (head)->prev, n = pos->prev; \
|
||||||
|
pos != (head); \
|
||||||
|
pos = n, n = pos->prev)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_entry - iterate over list of given type
|
||||||
|
* @pos: the type * to use as a loop cursor.
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the list_head within the struct.
|
||||||
|
*/
|
||||||
|
#define list_for_each_entry(pos, head, member) \
|
||||||
|
for (pos = list_first_entry(head, __typeof__(*pos), member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = list_next_entry(pos, member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_entry_reverse - iterate backwards over list of given type.
|
||||||
|
* @pos: the type * to use as a loop cursor.
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the list_head within the struct.
|
||||||
|
*/
|
||||||
|
#define list_for_each_entry_reverse(pos, head, member) \
|
||||||
|
for (pos = list_last_entry(head, __typeof__(*pos), member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = list_prev_entry(pos, member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
|
||||||
|
* @pos: the type * to use as a start point
|
||||||
|
* @head: the head of the list
|
||||||
|
* @member: the name of the list_head within the struct.
|
||||||
|
*
|
||||||
|
* Prepares a pos entry for use as a start point in list_for_each_entry_continue().
|
||||||
|
*/
|
||||||
|
#define list_prepare_entry(pos, head, member) \
|
||||||
|
((pos) ? : list_entry(head, __typeof__(*pos), member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_entry_continue - continue iteration over list of given type
|
||||||
|
* @pos: the type * to use as a loop cursor.
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the list_head within the struct.
|
||||||
|
*
|
||||||
|
* Continue to iterate over list of given type, continuing after
|
||||||
|
* the current position.
|
||||||
|
*/
|
||||||
|
#define list_for_each_entry_continue(pos, head, member) \
|
||||||
|
for (pos = list_next_entry(pos, member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = list_next_entry(pos, member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_entry_continue_reverse - iterate backwards from the given point
|
||||||
|
* @pos: the type * to use as a loop cursor.
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the list_head within the struct.
|
||||||
|
*
|
||||||
|
* Start to iterate over list of given type backwards, continuing after
|
||||||
|
* the current position.
|
||||||
|
*/
|
||||||
|
#define list_for_each_entry_continue_reverse(pos, head, member) \
|
||||||
|
for (pos = list_prev_entry(pos, member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = list_prev_entry(pos, member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_entry_from - iterate over list of given type from the current point
|
||||||
|
* @pos: the type * to use as a loop cursor.
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the list_head within the struct.
|
||||||
|
*
|
||||||
|
* Iterate over list of given type, continuing from current position.
|
||||||
|
*/
|
||||||
|
#define list_for_each_entry_from(pos, head, member) \
|
||||||
|
for (; &pos->member != (head); \
|
||||||
|
pos = list_next_entry(pos, member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||||||
|
* @pos: the type * to use as a loop cursor.
|
||||||
|
* @n: another type * to use as temporary storage
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the list_head within the struct.
|
||||||
|
*/
|
||||||
|
#define list_for_each_entry_safe(pos, n, head, member) \
|
||||||
|
for (pos = list_first_entry(head, __typeof__(*pos), member), \
|
||||||
|
n = list_next_entry(pos, member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = n, n = list_next_entry(n, member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_entry_safe_continue - continue list iteration safe against removal
|
||||||
|
* @pos: the type * to use as a loop cursor.
|
||||||
|
* @n: another type * to use as temporary storage
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the list_head within the struct.
|
||||||
|
*
|
||||||
|
* Iterate over list of given type, continuing after current point,
|
||||||
|
* safe against removal of list entry.
|
||||||
|
*/
|
||||||
|
#define list_for_each_entry_safe_continue(pos, n, head, member) \
|
||||||
|
for (pos = list_next_entry(pos, member), \
|
||||||
|
n = list_next_entry(pos, member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = n, n = list_next_entry(n, member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_entry_safe_from - iterate over list from current point safe against removal
|
||||||
|
* @pos: the type * to use as a loop cursor.
|
||||||
|
* @n: another type * to use as temporary storage
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the list_head within the struct.
|
||||||
|
*
|
||||||
|
* Iterate over list of given type from current point, safe against
|
||||||
|
* removal of list entry.
|
||||||
|
*/
|
||||||
|
#define list_for_each_entry_safe_from(pos, n, head, member) \
|
||||||
|
for (n = list_next_entry(pos, member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = n, n = list_next_entry(n, member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
|
||||||
|
* @pos: the type * to use as a loop cursor.
|
||||||
|
* @n: another type * to use as temporary storage
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the list_head within the struct.
|
||||||
|
*
|
||||||
|
* Iterate backwards over list of given type, safe against removal
|
||||||
|
* of list entry.
|
||||||
|
*/
|
||||||
|
#define list_for_each_entry_safe_reverse(pos, n, head, member) \
|
||||||
|
for (pos = list_last_entry(head, __typeof__(*pos), member), \
|
||||||
|
n = list_prev_entry(pos, member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = n, n = list_prev_entry(n, member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_safe_reset_next - reset a stale list_for_each_entry_safe loop
|
||||||
|
* @pos: the loop cursor used in the list_for_each_entry_safe loop
|
||||||
|
* @n: temporary storage used in list_for_each_entry_safe
|
||||||
|
* @member: the name of the list_head within the struct.
|
||||||
|
*
|
||||||
|
* list_safe_reset_next is not safe to use in general if the list may be
|
||||||
|
* modified concurrently (eg. the lock is dropped in the loop body). An
|
||||||
|
* exception to this is if the cursor element (pos) is pinned in the list,
|
||||||
|
* and list_safe_reset_next is called after re-taking the lock and before
|
||||||
|
* completing the current iteration of the loop body.
|
||||||
|
*/
|
||||||
|
#define list_safe_reset_next(pos, n, member) \
|
||||||
|
n = list_next_entry(pos, member)
|
||||||
|
|
||||||
|
#endif
|
@ -17,7 +17,7 @@ struct hw_profile
|
|||||||
{
|
{
|
||||||
enum AVCodecID av_codec;
|
enum AVCodecID av_codec;
|
||||||
int ff_profile;
|
int ff_profile;
|
||||||
uint64_t va_profile;
|
VAProfile va_profile;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ struct hw_profile
|
|||||||
static int drm_fd = 0;
|
static int drm_fd = 0;
|
||||||
static struct vaapi_context *v_context;
|
static struct vaapi_context *v_context;
|
||||||
|
|
||||||
static VASurfaceID v_surface_id[4];
|
static VASurfaceID v_surface_id[HWDEC_NUM_SURFACES];
|
||||||
|
|
||||||
#define HAS_HEVC VA_CHECK_VERSION(0, 38, 0)
|
#define HAS_HEVC VA_CHECK_VERSION(0, 38, 0)
|
||||||
#define HAS_VP9 (VA_CHECK_VERSION(0, 38, 1) && defined(FF_PROFILE_VP9_0))
|
#define HAS_VP9 (VA_CHECK_VERSION(0, 38, 1) && defined(FF_PROFILE_VP9_0))
|
||||||
@ -48,7 +48,7 @@ static VASurfaceID v_surface_id[4];
|
|||||||
{AV_CODEC_ID_ ## av_codec_id, FF_PROFILE_ ## ff_profile, \
|
{AV_CODEC_ID_ ## av_codec_id, FF_PROFILE_ ## ff_profile, \
|
||||||
VAProfile ## vdp_profile}
|
VAProfile ## vdp_profile}
|
||||||
|
|
||||||
static const struct hw_profile profiles[] = {
|
static const struct hw_profile hw_profiles[] = {
|
||||||
PE(MPEG2VIDEO, MPEG2_MAIN, MPEG2Main),
|
PE(MPEG2VIDEO, MPEG2_MAIN, MPEG2Main),
|
||||||
PE(MPEG2VIDEO, MPEG2_SIMPLE, MPEG2Simple),
|
PE(MPEG2VIDEO, MPEG2_SIMPLE, MPEG2Simple),
|
||||||
PE(MPEG4, MPEG4_ADVANCED_SIMPLE, MPEG4AdvancedSimple),
|
PE(MPEG4, MPEG4_ADVANCED_SIMPLE, MPEG4AdvancedSimple),
|
||||||
@ -75,8 +75,8 @@ static const struct hw_profile profiles[] = {
|
|||||||
|
|
||||||
int va_check_codec_support(enum AVCodecID id)
|
int va_check_codec_support(enum AVCodecID id)
|
||||||
{
|
{
|
||||||
for (int n = 0; profiles[n].av_codec; n++) {
|
for (int n = 0; hw_profiles[n].av_codec; n++) {
|
||||||
if (profiles[n].av_codec == id)
|
if (hw_profiles[n].av_codec == id)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -343,8 +343,7 @@ ENTER();
|
|||||||
|
|
||||||
printf("vaCreateSurfaces %dx%d\n",picture_width,picture_height);
|
printf("vaCreateSurfaces %dx%d\n",picture_width,picture_height);
|
||||||
status = vaCreateSurfaces(vaapi->display, VA_RT_FORMAT_YUV420, picture_width, picture_height,
|
status = vaCreateSurfaces(vaapi->display, VA_RT_FORMAT_YUV420, picture_width, picture_height,
|
||||||
v_surface_id,4,NULL,0);
|
v_surface_id,HWDEC_NUM_SURFACES,NULL,0);
|
||||||
printf("v_surface_id_3 %x\n", v_surface_id[3]);
|
|
||||||
if (!vaapi_check_status(status, "vaCreateSurfaces()"))
|
if (!vaapi_check_status(status, "vaCreateSurfaces()"))
|
||||||
{
|
{
|
||||||
FAIL();
|
FAIL();
|
||||||
@ -379,7 +378,7 @@ ENTER();
|
|||||||
status = vaCreateContext(vaapi->display, config_id,
|
status = vaCreateContext(vaapi->display, config_id,
|
||||||
picture_width, picture_height,
|
picture_width, picture_height,
|
||||||
VA_PROGRESSIVE,
|
VA_PROGRESSIVE,
|
||||||
v_surface_id, 4,
|
v_surface_id, HWDEC_NUM_SURFACES,
|
||||||
&context_id);
|
&context_id);
|
||||||
if (!vaapi_check_status(status, "vaCreateContext()"))
|
if (!vaapi_check_status(status, "vaCreateContext()"))
|
||||||
{
|
{
|
||||||
@ -397,41 +396,29 @@ ENTER();
|
|||||||
static enum PixelFormat get_format(struct AVCodecContext *avctx,
|
static enum PixelFormat get_format(struct AVCodecContext *avctx,
|
||||||
const enum AVPixelFormat *fmt)
|
const enum AVPixelFormat *fmt)
|
||||||
{
|
{
|
||||||
int i, profile;
|
VAProfile profile = VAProfileNone;
|
||||||
|
|
||||||
ENTER();
|
ENTER();
|
||||||
|
|
||||||
// for (int i = 0; fmt[i] != AV_PIX_FMT_NONE; i++)
|
for (int i = 0; fmt[i] != PIX_FMT_NONE; i++)
|
||||||
// printf(" %s", av_get_pix_fmt_name(fmt[i]));
|
{
|
||||||
|
enum AVCodecID codec = avctx->codec_id;
|
||||||
|
|
||||||
for (i = 0; fmt[i] != PIX_FMT_NONE; i++) {
|
|
||||||
printf("pixformat %x\n", fmt[i]);
|
|
||||||
if (fmt[i] != AV_PIX_FMT_VAAPI_VLD)
|
if (fmt[i] != AV_PIX_FMT_VAAPI_VLD)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
switch (avctx->codec_id)
|
if (codec == AV_CODEC_ID_H264)
|
||||||
{
|
{
|
||||||
case CODEC_ID_MPEG2VIDEO:
|
if (profile == FF_PROFILE_H264_CONSTRAINED_BASELINE)
|
||||||
profile = VAProfileMPEG2Main;
|
profile = FF_PROFILE_H264_MAIN;
|
||||||
break;
|
};
|
||||||
case CODEC_ID_MPEG4:
|
|
||||||
case CODEC_ID_H263:
|
for (int n = 0; hw_profiles[n].av_codec; n++)
|
||||||
profile = VAProfileMPEG4AdvancedSimple;
|
{
|
||||||
break;
|
if (hw_profiles[n].av_codec == codec &&
|
||||||
case CODEC_ID_H264:
|
hw_profiles[n].ff_profile == avctx->profile)
|
||||||
profile = VAProfileH264High;
|
{
|
||||||
break;
|
profile = hw_profiles[n].va_profile;
|
||||||
case CODEC_ID_WMV3:
|
|
||||||
profile = VAProfileVC1Main;
|
|
||||||
break;
|
|
||||||
case CODEC_ID_VC1:
|
|
||||||
profile = VAProfileVC1Advanced;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
profile = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (profile >= 0) {
|
|
||||||
if (vaapi_init_decoder(profile, VAEntrypointVLD, avctx->width, avctx->height) == 0)
|
if (vaapi_init_decoder(profile, VAEntrypointVLD, avctx->width, avctx->height) == 0)
|
||||||
{
|
{
|
||||||
avctx->hwaccel_context = v_context;
|
avctx->hwaccel_context = v_context;
|
||||||
@ -440,6 +427,8 @@ static enum PixelFormat get_format(struct AVCodecContext *avctx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
FAIL();
|
FAIL();
|
||||||
return PIX_FMT_NONE;
|
return PIX_FMT_NONE;
|
||||||
}
|
}
|
||||||
@ -454,16 +443,15 @@ struct av_surface
|
|||||||
static void av_release_buffer(void *opaque, uint8_t *data)
|
static void av_release_buffer(void *opaque, uint8_t *data)
|
||||||
{
|
{
|
||||||
struct av_surface surface = *(struct av_surface*)data;
|
struct av_surface surface = *(struct av_surface*)data;
|
||||||
// VDPAUContext *ctx = opaque;
|
|
||||||
|
|
||||||
// ctx->video_surface_destroy(surface);
|
|
||||||
av_freep(&data);
|
av_freep(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_buffer2(AVCodecContext *avctx, AVFrame *pic, int flags)
|
static int get_buffer2(AVCodecContext *avctx, AVFrame *pic, int flags)
|
||||||
{
|
{
|
||||||
vst_t *vst = (vst_t*)avctx->opaque;
|
vst_t *vst = (vst_t*)avctx->opaque;
|
||||||
void *surface = (void *)(uintptr_t)v_surface_id[vst->dfx];
|
void *surface;
|
||||||
|
|
||||||
|
surface = (void *)(uintptr_t)v_surface_id[vst->decoder_frame->index];
|
||||||
|
|
||||||
pic->data[3] = surface;
|
pic->data[3] = surface;
|
||||||
|
|
||||||
@ -493,20 +481,16 @@ int fplay_init_context(vst_t *vst)
|
|||||||
|
|
||||||
if(vst->hwCtx != NULL)
|
if(vst->hwCtx != NULL)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < 4; i++)
|
for(int i = 0; i < HWDEC_NUM_SURFACES; i++)
|
||||||
{
|
{
|
||||||
int ret;
|
vframe_t *vframe = calloc(1, sizeof(*vframe));
|
||||||
|
|
||||||
ret = avpicture_alloc(&vst->vframe[i].picture, AV_PIX_FMT_BGRA,
|
vframe->format = AV_PIX_FMT_NONE;
|
||||||
vst->vCtx->width, vst->vCtx->height);
|
vframe->is_hw_pic = 1;
|
||||||
if ( ret != 0 )
|
vframe->index = i;
|
||||||
{
|
vframe->pts = 0;
|
||||||
printf("Cannot alloc video buffer\n\r");
|
vframe->ready = 0;
|
||||||
return ret;
|
list_add_tail(&vframe->list, &vst->input_list);
|
||||||
};
|
|
||||||
vst->vframe[i].format = AV_PIX_FMT_BGRA;
|
|
||||||
vst->vframe[i].pts = 0;
|
|
||||||
vst->vframe[i].ready = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
vst->hwdec = 1;
|
vst->hwdec = 1;
|
||||||
@ -520,52 +504,119 @@ int fplay_init_context(vst_t *vst)
|
|||||||
|
|
||||||
vst->hwdec = 0;
|
vst->hwdec = 0;
|
||||||
|
|
||||||
for(int i = 0; i < 4; i++)
|
for(int i = 0; i < HWDEC_NUM_SURFACES; i++)
|
||||||
{
|
{
|
||||||
|
vframe_t *vframe;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = avpicture_alloc(&vst->vframe[i].picture, vst->vCtx->pix_fmt,
|
vframe = calloc(1, sizeof(*vframe));
|
||||||
|
|
||||||
|
ret = avpicture_alloc(&vframe->picture, vst->vCtx->pix_fmt,
|
||||||
vst->vCtx->width, vst->vCtx->height);
|
vst->vCtx->width, vst->vCtx->height);
|
||||||
if ( ret != 0 )
|
if ( ret != 0 )
|
||||||
{
|
{
|
||||||
printf("Cannot alloc video buffer\n\r");
|
printf("Cannot alloc video buffer\n\r");
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
vst->vframe[i].format = vst->vCtx->pix_fmt;
|
vframe->format = vst->vCtx->pix_fmt;
|
||||||
vst->vframe[i].pts = 0;
|
vframe->index = i;
|
||||||
vst->vframe[i].ready = 0;
|
vframe->pts = 0;
|
||||||
|
vframe->ready = 0;
|
||||||
|
list_add_tail(&vframe->list, &vst->input_list);
|
||||||
};
|
};
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct SwsContext *vacvt_ctx;
|
#define EGL_TEXTURE_Y_U_V_WL 0x31D7
|
||||||
|
#define EGL_TEXTURE_Y_UV_WL 0x31D8
|
||||||
|
#define EGL_TEXTURE_Y_XUXV_WL 0x31D9
|
||||||
|
|
||||||
void va_convert_picture(vst_t *vst, int width, int height, AVPicture *pic)
|
enum wl_drm_format {
|
||||||
|
WL_DRM_FORMAT_C8 = 0x20203843,
|
||||||
|
WL_DRM_FORMAT_RGB332 = 0x38424752,
|
||||||
|
WL_DRM_FORMAT_BGR233 = 0x38524742,
|
||||||
|
WL_DRM_FORMAT_XRGB4444 = 0x32315258,
|
||||||
|
WL_DRM_FORMAT_XBGR4444 = 0x32314258,
|
||||||
|
WL_DRM_FORMAT_RGBX4444 = 0x32315852,
|
||||||
|
WL_DRM_FORMAT_BGRX4444 = 0x32315842,
|
||||||
|
WL_DRM_FORMAT_ARGB4444 = 0x32315241,
|
||||||
|
WL_DRM_FORMAT_ABGR4444 = 0x32314241,
|
||||||
|
WL_DRM_FORMAT_RGBA4444 = 0x32314152,
|
||||||
|
WL_DRM_FORMAT_BGRA4444 = 0x32314142,
|
||||||
|
WL_DRM_FORMAT_XRGB1555 = 0x35315258,
|
||||||
|
WL_DRM_FORMAT_XBGR1555 = 0x35314258,
|
||||||
|
WL_DRM_FORMAT_RGBX5551 = 0x35315852,
|
||||||
|
WL_DRM_FORMAT_BGRX5551 = 0x35315842,
|
||||||
|
WL_DRM_FORMAT_ARGB1555 = 0x35315241,
|
||||||
|
WL_DRM_FORMAT_ABGR1555 = 0x35314241,
|
||||||
|
WL_DRM_FORMAT_RGBA5551 = 0x35314152,
|
||||||
|
WL_DRM_FORMAT_BGRA5551 = 0x35314142,
|
||||||
|
WL_DRM_FORMAT_RGB565 = 0x36314752,
|
||||||
|
WL_DRM_FORMAT_BGR565 = 0x36314742,
|
||||||
|
WL_DRM_FORMAT_RGB888 = 0x34324752,
|
||||||
|
WL_DRM_FORMAT_BGR888 = 0x34324742,
|
||||||
|
WL_DRM_FORMAT_XRGB8888 = 0x34325258,
|
||||||
|
WL_DRM_FORMAT_XBGR8888 = 0x34324258,
|
||||||
|
WL_DRM_FORMAT_RGBX8888 = 0x34325852,
|
||||||
|
WL_DRM_FORMAT_BGRX8888 = 0x34325842,
|
||||||
|
WL_DRM_FORMAT_ARGB8888 = 0x34325241,
|
||||||
|
WL_DRM_FORMAT_ABGR8888 = 0x34324241,
|
||||||
|
WL_DRM_FORMAT_RGBA8888 = 0x34324152,
|
||||||
|
WL_DRM_FORMAT_BGRA8888 = 0x34324142,
|
||||||
|
WL_DRM_FORMAT_XRGB2101010 = 0x30335258,
|
||||||
|
WL_DRM_FORMAT_XBGR2101010 = 0x30334258,
|
||||||
|
WL_DRM_FORMAT_RGBX1010102 = 0x30335852,
|
||||||
|
WL_DRM_FORMAT_BGRX1010102 = 0x30335842,
|
||||||
|
WL_DRM_FORMAT_ARGB2101010 = 0x30335241,
|
||||||
|
WL_DRM_FORMAT_ABGR2101010 = 0x30334241,
|
||||||
|
WL_DRM_FORMAT_RGBA1010102 = 0x30334152,
|
||||||
|
WL_DRM_FORMAT_BGRA1010102 = 0x30334142,
|
||||||
|
WL_DRM_FORMAT_YUYV = 0x56595559,
|
||||||
|
WL_DRM_FORMAT_YVYU = 0x55595659,
|
||||||
|
WL_DRM_FORMAT_UYVY = 0x59565955,
|
||||||
|
WL_DRM_FORMAT_VYUY = 0x59555956,
|
||||||
|
WL_DRM_FORMAT_AYUV = 0x56555941,
|
||||||
|
WL_DRM_FORMAT_NV12 = 0x3231564e,
|
||||||
|
WL_DRM_FORMAT_NV21 = 0x3132564e,
|
||||||
|
WL_DRM_FORMAT_NV16 = 0x3631564e,
|
||||||
|
WL_DRM_FORMAT_NV61 = 0x3136564e,
|
||||||
|
WL_DRM_FORMAT_YUV410 = 0x39565559,
|
||||||
|
WL_DRM_FORMAT_YVU410 = 0x39555659,
|
||||||
|
WL_DRM_FORMAT_YUV411 = 0x31315559,
|
||||||
|
WL_DRM_FORMAT_YVU411 = 0x31315659,
|
||||||
|
WL_DRM_FORMAT_YUV420 = 0x32315559,
|
||||||
|
WL_DRM_FORMAT_YVU420 = 0x32315659,
|
||||||
|
WL_DRM_FORMAT_YUV422 = 0x36315559,
|
||||||
|
WL_DRM_FORMAT_YVU422 = 0x36315659,
|
||||||
|
WL_DRM_FORMAT_YUV444 = 0x34325559,
|
||||||
|
WL_DRM_FORMAT_YVU444 = 0x34325659,
|
||||||
|
};
|
||||||
|
|
||||||
|
void va_create_planar(vst_t *vst, vframe_t *vframe)
|
||||||
{
|
{
|
||||||
uint8_t *src_data[4];
|
struct vaapi_context* const vaapi = v_context;
|
||||||
int src_linesize[4];
|
VABufferInfo info = {0};
|
||||||
|
|
||||||
VAImage vaimage;
|
VAImage vaimage;
|
||||||
VAStatus status;
|
VAStatus status;
|
||||||
uint8_t *vdata;
|
planar_t *planar;
|
||||||
struct vaapi_context* const vaapi = v_context;
|
|
||||||
|
|
||||||
vaSyncSurface(vaapi->display,v_surface_id[vst->dfx]);
|
vaSyncSurface(vaapi->display,v_surface_id[vframe->index]);
|
||||||
|
|
||||||
status = vaDeriveImage(vaapi->display,v_surface_id[vst->dfx],&vaimage);
|
if(vframe->format != AV_PIX_FMT_NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ENTER();
|
||||||
|
|
||||||
|
status = vaDeriveImage(vaapi->display,v_surface_id[vframe->index],&vaimage);
|
||||||
if (!vaapi_check_status(status, "vaDeriveImage()"))
|
if (!vaapi_check_status(status, "vaDeriveImage()"))
|
||||||
{
|
{
|
||||||
FAIL();
|
FAIL();
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
/*
|
||||||
static int once = 2;
|
|
||||||
|
|
||||||
if(once && vst->dfx == 0)
|
|
||||||
{
|
|
||||||
VABufferInfo info = {0};
|
|
||||||
|
|
||||||
printf("vaDeriveImage: %x fourcc: %x\n"
|
printf("vaDeriveImage: %x fourcc: %x\n"
|
||||||
"offset0: %d pitch0: %d\n"
|
"offset0: %d pitch0: %d\n"
|
||||||
"offset1: %d pitch1: %d\n"
|
"offset1: %d pitch1: %d\n"
|
||||||
@ -574,53 +625,33 @@ void va_convert_picture(vst_t *vst, int width, int height, AVPicture *pic)
|
|||||||
vaimage.offsets[0],vaimage.pitches[0],
|
vaimage.offsets[0],vaimage.pitches[0],
|
||||||
vaimage.offsets[1],vaimage.pitches[1],
|
vaimage.offsets[1],vaimage.pitches[1],
|
||||||
vaimage.offsets[2],vaimage.pitches[2]);
|
vaimage.offsets[2],vaimage.pitches[2]);
|
||||||
|
*/
|
||||||
info.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM;
|
info.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM;
|
||||||
status = vaAcquireBufferHandle(vaapi->display, vaimage.buf, &info);
|
status = vaAcquireBufferHandle(vaapi->display, vaimage.buf, &info);
|
||||||
if (vaapi_check_status(status, "vaAcquireBufferHandle()"))
|
if (!vaapi_check_status(status, "vaAcquireBufferHandle()"))
|
||||||
{
|
|
||||||
printf("vaAcquireBufferHandle: %x type: %x\n"
|
|
||||||
"mem type: %x mem size: %d\n",
|
|
||||||
info.handle, info.type, info.mem_type, info.mem_size);
|
|
||||||
|
|
||||||
vaReleaseBufferHandle(vaapi->display, vaimage.buf);
|
|
||||||
}
|
|
||||||
once--;
|
|
||||||
};
|
|
||||||
|
|
||||||
src_linesize[0] = vaimage.pitches[0];
|
|
||||||
src_linesize[1] = vaimage.pitches[1];
|
|
||||||
src_linesize[2] = vaimage.pitches[2];
|
|
||||||
src_linesize[3] = 0;
|
|
||||||
|
|
||||||
status = vaMapBuffer(vaapi->display,vaimage.buf,(void **)&vdata);
|
|
||||||
if (!vaapi_check_status(status, "vaMapBuffer()"))
|
|
||||||
{
|
{
|
||||||
|
vaDestroyImage(vaapi->display, vaimage.image_id);
|
||||||
FAIL();
|
FAIL();
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
/*
|
||||||
// printf("vdata: %x offset0: %d offset1: %d offset2: %d\n", vdata,
|
printf("vaAcquireBufferHandle: %x type: %x\n"
|
||||||
// vaimage.offsets[0],
|
"mem type: %x mem size: %d\n",
|
||||||
// vaimage.offsets[1],
|
info.handle, info.type, info.mem_type, info.mem_size);
|
||||||
// vaimage.offsets[2]);
|
*/
|
||||||
|
planar = pxCreatePlanar(info.handle, WL_DRM_FORMAT_NV12,
|
||||||
src_data[0] = vdata + vaimage.offsets[0];
|
vaimage.width, vaimage.height,
|
||||||
src_data[1] = vdata + vaimage.offsets[1];
|
vaimage.offsets[0],vaimage.pitches[0],
|
||||||
src_data[2] = vdata + vaimage.offsets[2];
|
vaimage.offsets[1],vaimage.pitches[1],
|
||||||
src_data[3] = 0;
|
vaimage.offsets[2],vaimage.pitches[2]);
|
||||||
|
if(planar != NULL)
|
||||||
vacvt_ctx = sws_getCachedContext(vacvt_ctx, width, height, AV_PIX_FMT_NV12,
|
|
||||||
width, height, AV_PIX_FMT_BGRA,
|
|
||||||
SWS_FAST_BILINEAR, NULL, NULL, NULL);
|
|
||||||
if(vacvt_ctx == NULL)
|
|
||||||
{
|
{
|
||||||
printf("Cannot initialize the conversion context!\n");
|
printf("create planar image\n",planar);
|
||||||
return ;
|
vframe->planar = planar;
|
||||||
|
vframe->format = AV_PIX_FMT_NV12;
|
||||||
};
|
};
|
||||||
|
|
||||||
sws_scale(vacvt_ctx, (const uint8_t* const *)src_data, src_linesize, 0, height, pic->data, pic->linesize);
|
vaReleaseBufferHandle(vaapi->display, vaimage.buf);
|
||||||
|
|
||||||
vaUnmapBuffer (vaapi->display, vaimage.buf);
|
|
||||||
vaDestroyImage(vaapi->display, vaimage.image_id);
|
vaDestroyImage(vaapi->display, vaimage.image_id);
|
||||||
|
LEAVE();
|
||||||
}
|
}
|
||||||
|
@ -28,35 +28,38 @@ struct SwsContext *cvt_ctx = NULL;
|
|||||||
|
|
||||||
render_t *main_render;
|
render_t *main_render;
|
||||||
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
|
|
||||||
AVRational video_time_base;
|
AVRational video_time_base;
|
||||||
AVFrame *Frame;
|
AVFrame *Frame;
|
||||||
|
|
||||||
void get_client_rect(rect_t *rc);
|
void get_client_rect(rect_t *rc);
|
||||||
|
void run_render(window_t *win, void *render);
|
||||||
|
void window_update_layout(window_t *win);
|
||||||
|
int fini_winlib();
|
||||||
|
|
||||||
void flush_video(vst_t *vst)
|
void flush_video(vst_t *vst)
|
||||||
{
|
{
|
||||||
int i;
|
vframe_t *vframe, *tmp;
|
||||||
|
|
||||||
for(i = 0; i < 4; i++)
|
mutex_lock(&vst->output_lock);
|
||||||
|
mutex_lock(&vst->input_lock);
|
||||||
|
|
||||||
|
list_for_each_entry_safe(vframe, tmp, &vst->output_list, list)
|
||||||
|
list_move_tail(&vframe->list, &vst->input_list);
|
||||||
|
|
||||||
|
list_for_each_entry(vframe, &vst->output_list, list)
|
||||||
{
|
{
|
||||||
vst->vframe[i].pts = 0;
|
vframe->pts = 0;
|
||||||
vst->vframe[i].ready = 0;
|
vframe->ready = 0;
|
||||||
};
|
}
|
||||||
vst->vfx = 0;
|
|
||||||
vst->dfx = 0;
|
mutex_unlock(&vst->input_lock);
|
||||||
|
mutex_unlock(&vst->output_lock);
|
||||||
|
|
||||||
frames_count = 0;
|
frames_count = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
int init_video(vst_t *vst)
|
int init_video(vst_t *vst)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
width = vst->vCtx->width;
|
|
||||||
height = vst->vCtx->height;
|
|
||||||
|
|
||||||
Frame = av_frame_alloc();
|
Frame = av_frame_alloc();
|
||||||
if ( Frame == NULL )
|
if ( Frame == NULL )
|
||||||
{
|
{
|
||||||
@ -64,44 +67,44 @@ int init_video(vst_t *vst)
|
|||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mutex_lock(&vst->decoder_lock);
|
||||||
|
|
||||||
create_thread(video_thread, vst, 1024*1024);
|
create_thread(video_thread, vst, 1024*1024);
|
||||||
|
|
||||||
delay(50);
|
|
||||||
return 1;
|
return 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static double dts = 0.0;
|
||||||
|
|
||||||
int decode_video(vst_t* vst)
|
int decode_video(vst_t* vst)
|
||||||
{
|
{
|
||||||
AVPacket pkt;
|
AVPacket pkt;
|
||||||
double pts;
|
double pts;
|
||||||
int frameFinished;
|
int frameFinished;
|
||||||
double current_clock;
|
|
||||||
|
|
||||||
if(vst->vframe[vst->dfx].ready != 0 )
|
if(vst->decoder_frame == NULL)
|
||||||
|
{
|
||||||
|
mutex_lock(&vst->input_lock);
|
||||||
|
if(list_empty(&vst->input_list))
|
||||||
|
{
|
||||||
|
mutex_unlock(&vst->input_lock);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
vst->decoder_frame = list_first_entry(&vst->input_list, vframe_t, list);
|
||||||
|
list_del(&vst->decoder_frame->list);
|
||||||
|
mutex_unlock(&vst->input_lock);
|
||||||
|
|
||||||
|
vframe_t *vframe = vst->decoder_frame;
|
||||||
|
};
|
||||||
|
|
||||||
if( get_packet(&vst->q_video, &pkt) == 0 )
|
if( get_packet(&vst->q_video, &pkt) == 0 )
|
||||||
return 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
current_clock = -90.0 + get_master_clock();
|
|
||||||
|
|
||||||
if( pkt.dts == AV_NOPTS_VALUE &&
|
|
||||||
Frame->reordered_opaque != AV_NOPTS_VALUE)
|
|
||||||
pts = Frame->reordered_opaque;
|
|
||||||
else if(pkt.dts != AV_NOPTS_VALUE)
|
|
||||||
pts= pkt.dts;
|
|
||||||
else
|
|
||||||
pts= 0;
|
|
||||||
|
|
||||||
|
|
||||||
pts *= av_q2d(video_time_base)*1000.0;
|
|
||||||
*/
|
|
||||||
if( 1 /*pts > current_clock*/)
|
|
||||||
{
|
{
|
||||||
frameFinished = 0;
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
vst->vCtx->reordered_opaque = pkt.pts;
|
frameFinished = 0;
|
||||||
|
if(dts == 0)
|
||||||
|
dts = pkt.pts;
|
||||||
|
|
||||||
mutex_lock(&vst->gpu_lock);
|
mutex_lock(&vst->gpu_lock);
|
||||||
|
|
||||||
@ -110,35 +113,67 @@ int decode_video(vst_t* vst)
|
|||||||
|
|
||||||
if(frameFinished)
|
if(frameFinished)
|
||||||
{
|
{
|
||||||
|
vframe_t *vframe;
|
||||||
AVPicture *dst_pic;
|
AVPicture *dst_pic;
|
||||||
|
|
||||||
if( pkt.dts == AV_NOPTS_VALUE &&
|
pts = av_frame_get_best_effort_timestamp(Frame);
|
||||||
Frame->reordered_opaque != AV_NOPTS_VALUE)
|
|
||||||
pts = Frame->reordered_opaque;
|
|
||||||
else if(pkt.dts != AV_NOPTS_VALUE)
|
|
||||||
pts = pkt.dts;
|
|
||||||
else
|
|
||||||
pts = 0;
|
|
||||||
|
|
||||||
pts *= av_q2d(video_time_base);
|
pts *= av_q2d(video_time_base);
|
||||||
|
|
||||||
dst_pic = &vst->vframe[vst->dfx].picture;
|
vframe = vst->decoder_frame;
|
||||||
|
dst_pic = &vframe->picture;
|
||||||
|
|
||||||
if(vst->hwdec == 0)
|
if(vframe->is_hw_pic == 0)
|
||||||
av_image_copy(dst_pic->data, dst_pic->linesize,
|
av_image_copy(dst_pic->data, dst_pic->linesize,
|
||||||
(const uint8_t**)Frame->data,
|
(const uint8_t**)Frame->data,
|
||||||
Frame->linesize, vst->vCtx->pix_fmt, vst->vCtx->width, vst->vCtx->height);
|
Frame->linesize, vst->vCtx->pix_fmt, vst->vCtx->width, vst->vCtx->height);
|
||||||
else
|
else
|
||||||
va_convert_picture(vst, vst->vCtx->width, vst->vCtx->height, dst_pic);
|
va_create_planar(vst, vframe);
|
||||||
|
|
||||||
vst->vframe[vst->dfx].pts = pts*1000.0;
|
vframe->pts = pts*1000.0;
|
||||||
vst->vframe[vst->dfx].ready = 1;
|
vframe->pkt_pts = pkt.pts*av_q2d(video_time_base)*1000.0;
|
||||||
vst->dfx = (vst->dfx + 1) & 3;
|
vframe->pkt_dts = dts*av_q2d(video_time_base)*1000.0;
|
||||||
frames_count++;
|
vframe->ready = 1;
|
||||||
|
|
||||||
|
|
||||||
|
mutex_lock(&vst->output_lock);
|
||||||
|
|
||||||
|
if(list_empty(&vst->output_list))
|
||||||
|
list_add_tail(&vframe->list, &vst->output_list);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vframe_t *cur;
|
||||||
|
|
||||||
|
cur = list_first_entry(&vst->output_list,vframe_t,list);
|
||||||
|
if(vframe->pkt_pts < cur->pkt_pts)
|
||||||
|
{
|
||||||
|
list_add_tail(&vframe->list, &vst->output_list);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list_for_each_entry_reverse(cur,&vst->output_list,list)
|
||||||
|
{
|
||||||
|
if(vframe->pkt_pts > cur->pkt_pts)
|
||||||
|
{
|
||||||
|
list_add(&vframe->list, &cur->list);
|
||||||
|
break;
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
mutex_unlock(&vst->output_lock);
|
||||||
|
|
||||||
|
|
||||||
|
// printf("decoded index: %d pts: %f pkt_pts %f pkt_dts %f\n",
|
||||||
|
// vst->dfx, vst->vframe[vst->dfx].pts,
|
||||||
|
// vst->vframe[vst->dfx].pkt_pts, vst->vframe[vst->dfx].pkt_dts);
|
||||||
|
|
||||||
|
vst->decoder_frame = NULL;
|
||||||
|
frames_count++;
|
||||||
|
dts = 0;
|
||||||
|
};
|
||||||
|
av_frame_unref(Frame);
|
||||||
mutex_unlock(&vst->gpu_lock);
|
mutex_unlock(&vst->gpu_lock);
|
||||||
|
|
||||||
};
|
|
||||||
av_free_packet(&pkt);
|
av_free_packet(&pkt);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -357,8 +392,6 @@ int MainWindowProc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2)
|
|||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define VERSION_A 1
|
|
||||||
|
|
||||||
void render_time(render_t *render)
|
void render_time(render_t *render)
|
||||||
{
|
{
|
||||||
progress_t *prg = main_render->win->panel.prg;
|
progress_t *prg = main_render->win->panel.prg;
|
||||||
@ -367,8 +400,6 @@ void render_time(render_t *render)
|
|||||||
double ctime; /* milliseconds */
|
double ctime; /* milliseconds */
|
||||||
double fdelay; /* milliseconds */
|
double fdelay; /* milliseconds */
|
||||||
|
|
||||||
//again:
|
|
||||||
|
|
||||||
if(player_state == CLOSED)
|
if(player_state == CLOSED)
|
||||||
{
|
{
|
||||||
render->win->win_command = WIN_CLOSED;
|
render->win->win_command = WIN_CLOSED;
|
||||||
@ -390,51 +421,38 @@ void render_time(render_t *render)
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mutex_lock(&vst->output_lock);
|
||||||
#ifdef VERSION_A
|
if(list_empty(&vst->output_list))
|
||||||
if(vst->vframe[vst->vfx].ready == 1 )
|
|
||||||
{
|
{
|
||||||
|
mutex_unlock(&vst->output_lock);
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vframe_t *vframe;
|
||||||
int sys_time;
|
int sys_time;
|
||||||
|
|
||||||
ctime = get_master_clock();
|
vframe = list_first_entry(&vst->output_list, vframe_t, list);
|
||||||
fdelay = (vst->vframe[vst->vfx].pts - ctime);
|
list_del(&vframe->list);
|
||||||
|
mutex_unlock(&vst->output_lock);
|
||||||
|
|
||||||
// printf("pts %f time %f delay %f\n",
|
ctime = get_master_clock();
|
||||||
// frames[vfx].pts, ctime, fdelay);
|
fdelay = (vframe->pkt_pts - ctime);
|
||||||
|
|
||||||
if(fdelay > 15.0)
|
if(fdelay > 15.0)
|
||||||
{
|
{
|
||||||
delay((int)fdelay/10);
|
delay((int)fdelay/10);
|
||||||
// return;
|
|
||||||
};
|
};
|
||||||
#if 0
|
|
||||||
ctime = get_master_clock();
|
|
||||||
fdelay = (vst->vframe[vst->vfx].pts - ctime);
|
|
||||||
|
|
||||||
// while(fdelay > 0)
|
// printf("output index: %d pts: %f pkt_pts %f pkt_dts %f\n",
|
||||||
// {
|
// vframe->index,vframe->pts,vframe->pkt_pts,vframe->pkt_dts);
|
||||||
// yield();
|
|
||||||
// ctime = get_master_clock();
|
|
||||||
// fdelay = (frames[vfx].pts - ctime);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// sys_time = get_tick_count();
|
main_render->draw(main_render, vframe);
|
||||||
|
|
||||||
// if(fdelay < 0)
|
|
||||||
// printf("systime %d pts %f time %f delay %f\n",
|
|
||||||
// sys_time*10, frames[vfx].pts, ctime, fdelay);
|
|
||||||
|
|
||||||
printf("pts %f time %f delay %f\n",
|
|
||||||
vst->vframe[vst->vfx].pts, ctime, fdelay);
|
|
||||||
printf("video cache %d audio cache %d\n", q_video.size/1024, q_audio.size/1024);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
main_render->draw(main_render, &vst->vframe[vst->vfx].picture);
|
|
||||||
if(main_render->win->win_state != FULLSCREEN)
|
if(main_render->win->win_state != FULLSCREEN)
|
||||||
{
|
{
|
||||||
prg->current = vst->vframe[vst->vfx].pts*1000;
|
prg->current = vframe->pkt_pts * 1000;
|
||||||
// printf("current %f\n", prg->current);
|
lvl->current = vframe->index & 1 ? sound_level_1 : sound_level_0;
|
||||||
lvl->current = vst->vfx & 1 ? sound_level_1 : sound_level_0;
|
|
||||||
|
|
||||||
send_message(&prg->ctrl, PRG_PROGRESS, 0, 0);
|
send_message(&prg->ctrl, PRG_PROGRESS, 0, 0);
|
||||||
|
|
||||||
@ -443,69 +461,12 @@ void render_time(render_t *render)
|
|||||||
}
|
}
|
||||||
|
|
||||||
frames_count--;
|
frames_count--;
|
||||||
vst->vframe[vst->vfx].ready = 0;
|
vframe->ready = 0;
|
||||||
vst->vfx = (vst->vfx + 1) & 3;
|
|
||||||
|
mutex_lock(&vst->input_lock);
|
||||||
|
list_add_tail(&vframe->list, &vst->input_list);
|
||||||
|
mutex_unlock(&vst->input_lock);
|
||||||
}
|
}
|
||||||
else delay(1);
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
if(vst->vframe[vfx].ready == 1 )
|
|
||||||
{
|
|
||||||
ctime = get_master_clock();
|
|
||||||
fdelay = (vst->vrame[vst->vfx].pts - ctime);
|
|
||||||
|
|
||||||
// printf("pts %f time %f delay %f\n",
|
|
||||||
// frames[vfx].pts, ctime, fdelay);
|
|
||||||
|
|
||||||
if(fdelay < 0.0 )
|
|
||||||
{
|
|
||||||
int next_vfx;
|
|
||||||
fdelay = 0;
|
|
||||||
next_vfx = (vst->vfx+1) & 3;
|
|
||||||
if( vst->vrame[next_vfx].ready == 1 )
|
|
||||||
{
|
|
||||||
if(vst->vrame[next_vfx].pts <= ctime)
|
|
||||||
{
|
|
||||||
vst->vrame[vst->vfx].ready = 0; // skip this frame
|
|
||||||
vst->vfx = (vst->vfx + 1) & 3;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if( (vst->vrame[next_vfx].pts - ctime) <
|
|
||||||
( ctime - frames[vst->vfx].pts) )
|
|
||||||
{
|
|
||||||
vst->vrame[vst->vfx].ready = 0; // skip this frame
|
|
||||||
vst->vfx = (vst->vfx + 1) & 3;
|
|
||||||
fdelay = (vst->vrame[next_vfx].pts - ctime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
if(fdelay > 10.0)
|
|
||||||
{
|
|
||||||
int val = fdelay;
|
|
||||||
printf("pts %f time %f delay %d\n",
|
|
||||||
vst->vrame[vst->vfx].pts, ctime, val);
|
|
||||||
delay(val/10);
|
|
||||||
};
|
|
||||||
|
|
||||||
ctime = get_master_clock();
|
|
||||||
fdelay = (vst->vrame[vst->vfx].pts - ctime);
|
|
||||||
|
|
||||||
printf("pts %f time %f delay %f\n",
|
|
||||||
vst->vrame[vst->vfx].pts, ctime, fdelay);
|
|
||||||
|
|
||||||
main_render->draw(main_render, &vst->vrame[vfx].picture);
|
|
||||||
main_render->win->panel.prg->current = vst->vrame[vfx].pts;
|
|
||||||
// send_message(&render->win->panel.prg->ctrl, MSG_PAINT, 0, 0);
|
|
||||||
vst->vrame[vst->vfx].ready = 0;
|
|
||||||
vst->vfx = (vst->vfx + 1) & 3;
|
|
||||||
}
|
|
||||||
else yield();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -519,7 +480,7 @@ int video_thread(void *param)
|
|||||||
init_winlib();
|
init_winlib();
|
||||||
|
|
||||||
MainWindow = create_window(movie_file,0,
|
MainWindow = create_window(movie_file,0,
|
||||||
10,10,width,height+CAPTION_HEIGHT+PANEL_HEIGHT,MainWindowProc);
|
10,10,vst->vCtx->width,vst->vCtx->height+CAPTION_HEIGHT+PANEL_HEIGHT,MainWindowProc);
|
||||||
|
|
||||||
MainWindow->panel.prg->max = stream_duration;
|
MainWindow->panel.prg->max = stream_duration;
|
||||||
|
|
||||||
@ -528,6 +489,7 @@ int video_thread(void *param)
|
|||||||
main_render = create_render(vst, MainWindow, HW_TEX_BLIT|HW_BIT_BLIT);
|
main_render = create_render(vst, MainWindow, HW_TEX_BLIT|HW_BIT_BLIT);
|
||||||
if( main_render == NULL)
|
if( main_render == NULL)
|
||||||
{
|
{
|
||||||
|
mutex_unlock(&vst->decoder_lock);
|
||||||
printf("Cannot create render\n\r");
|
printf("Cannot create render\n\r");
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
@ -537,6 +499,8 @@ int video_thread(void *param)
|
|||||||
render_draw_client(main_render);
|
render_draw_client(main_render);
|
||||||
player_state = PLAY;
|
player_state = PLAY;
|
||||||
|
|
||||||
|
mutex_unlock(&vst->decoder_lock);
|
||||||
|
|
||||||
run_render(MainWindow, main_render);
|
run_render(MainWindow, main_render);
|
||||||
|
|
||||||
__sync_and_and_fetch(&threads_running,~VIDEO_THREAD);
|
__sync_and_and_fetch(&threads_running,~VIDEO_THREAD);
|
||||||
@ -548,8 +512,8 @@ int video_thread(void *param)
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void draw_hw_picture(render_t *render, AVPicture *picture);
|
void draw_hw_picture(render_t *render, vframe_t *vframe);
|
||||||
void draw_sw_picture(render_t *render, AVPicture *picture);
|
void draw_sw_picture(render_t *render, vframe_t *vframe);
|
||||||
|
|
||||||
render_t *create_render(vst_t *vst, window_t *win, uint32_t flags)
|
render_t *create_render(vst_t *vst, window_t *win, uint32_t flags)
|
||||||
{
|
{
|
||||||
@ -783,8 +747,26 @@ void render_adjust_size(render_t *render, window_t *win)
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
void draw_hw_picture(render_t *render, AVPicture *picture)
|
static void render_hw_planar(render_t *render, vframe_t *vframe)
|
||||||
{
|
{
|
||||||
|
vst_t *vst = render->vst;
|
||||||
|
planar_t *planar = vframe->planar;
|
||||||
|
|
||||||
|
if(vframe->is_hw_pic != 0 && vframe->format != AV_PIX_FMT_NONE)
|
||||||
|
{
|
||||||
|
mutex_lock(&render->vst->gpu_lock);
|
||||||
|
|
||||||
|
pxBlitPlanar(planar, render->rcvideo.l,
|
||||||
|
CAPTION_HEIGHT+render->rcvideo.t,
|
||||||
|
render->rcvideo.r, render->rcvideo.b,0,0);
|
||||||
|
mutex_unlock(&render->vst->gpu_lock);
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void draw_hw_picture(render_t *render, vframe_t *vframe)
|
||||||
|
{
|
||||||
|
AVPicture *picture;
|
||||||
int dst_width;
|
int dst_width;
|
||||||
int dst_height;
|
int dst_height;
|
||||||
bitmap_t *bitmap;
|
bitmap_t *bitmap;
|
||||||
@ -794,6 +776,8 @@ void draw_hw_picture(render_t *render, AVPicture *picture)
|
|||||||
int linesize[4];
|
int linesize[4];
|
||||||
enum AVPixelFormat format;
|
enum AVPixelFormat format;
|
||||||
|
|
||||||
|
vst_t *vst = render->vst;
|
||||||
|
|
||||||
if(render->win->win_state == MINIMIZED ||
|
if(render->win->win_state == MINIMIZED ||
|
||||||
render->win->win_state == ROLLED)
|
render->win->win_state == ROLLED)
|
||||||
return;
|
return;
|
||||||
@ -809,9 +793,16 @@ void draw_hw_picture(render_t *render, AVPicture *picture)
|
|||||||
dst_height = render->rcvideo.b;
|
dst_height = render->rcvideo.b;
|
||||||
};
|
};
|
||||||
|
|
||||||
format = render->vst->hwdec == 0 ? render->ctx_format : AV_PIX_FMT_BGRA
|
if(vst->hwdec)
|
||||||
cvt_ctx = sws_getCachedContext(cvt_ctx,
|
{
|
||||||
render->ctx_width, render->ctx_height, format,
|
render_hw_planar(render, vframe);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
picture = &vframe->picture;
|
||||||
|
|
||||||
|
format = render->vst->hwdec == 0 ? render->ctx_format : AV_PIX_FMT_BGRA;
|
||||||
|
cvt_ctx = sws_getCachedContext(cvt_ctx, render->ctx_width, render->ctx_height, format,
|
||||||
dst_width, dst_height, AV_PIX_FMT_BGRA,
|
dst_width, dst_height, AV_PIX_FMT_BGRA,
|
||||||
SWS_FAST_BILINEAR, NULL, NULL, NULL);
|
SWS_FAST_BILINEAR, NULL, NULL, NULL);
|
||||||
if(cvt_ctx == NULL)
|
if(cvt_ctx == NULL)
|
||||||
@ -829,7 +820,6 @@ void draw_hw_picture(render_t *render, AVPicture *picture)
|
|||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// printf("sws_getCachedContext\n");
|
|
||||||
data[0] = bitmap_data;
|
data[0] = bitmap_data;
|
||||||
data[1] = bitmap_data+1;
|
data[1] = bitmap_data+1;
|
||||||
data[2] = bitmap_data+2;
|
data[2] = bitmap_data+2;
|
||||||
@ -874,8 +864,9 @@ void draw_hw_picture(render_t *render, AVPicture *picture)
|
|||||||
render->target&= 1;
|
render->target&= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_sw_picture(render_t *render, AVPicture *picture)
|
void draw_sw_picture(render_t *render, vframe_t *vframe)
|
||||||
{
|
{
|
||||||
|
AVPicture *picture;
|
||||||
uint8_t *bitmap_data;
|
uint8_t *bitmap_data;
|
||||||
uint32_t bitmap_pitch;
|
uint32_t bitmap_pitch;
|
||||||
uint8_t *data[4];
|
uint8_t *data[4];
|
||||||
@ -885,6 +876,8 @@ void draw_sw_picture(render_t *render, AVPicture *picture)
|
|||||||
render->win->win_state == ROLLED)
|
render->win->win_state == ROLLED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
picture = &vframe->picture;
|
||||||
|
|
||||||
cvt_ctx = sws_getCachedContext(cvt_ctx,
|
cvt_ctx = sws_getCachedContext(cvt_ctx,
|
||||||
render->ctx_width, render->ctx_height,
|
render->ctx_width, render->ctx_height,
|
||||||
render->ctx_format,
|
render->ctx_format,
|
||||||
@ -937,9 +930,9 @@ void render_draw_client(render_t *render)
|
|||||||
|
|
||||||
if(player_state == PAUSE)
|
if(player_state == PAUSE)
|
||||||
{
|
{
|
||||||
if(vst->vframe[vst->vfx].ready == 1 )
|
// if(vst->vframe[vst->vfx].ready == 1 )
|
||||||
main_render->draw(main_render, &vst->vframe[vst->vfx].picture);
|
// main_render->draw(main_render, &vst->vframe[vst->vfx].picture);
|
||||||
else
|
// else
|
||||||
draw_bar(0, y, render->win_width,
|
draw_bar(0, y, render->win_width,
|
||||||
render->rcvideo.b, 0);
|
render->rcvideo.b, 0);
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ static inline void list_remove(link_t *link)
|
|||||||
link_initialize(link);
|
link_initialize(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int list_empty(link_t *head)
|
static inline int llist_empty(link_t *head)
|
||||||
{
|
{
|
||||||
return head->next == head ? 1 : 0;
|
return head->next == head ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,9 @@ static int need_update;
|
|||||||
|
|
||||||
|
|
||||||
void adjust_frame(window_t *win);
|
void adjust_frame(window_t *win);
|
||||||
|
void blit_panel(panel_t *panel);
|
||||||
|
void update_panel_size(window_t *win);
|
||||||
|
void update_caption_size(window_t *win);
|
||||||
|
|
||||||
//#include "timer.h"
|
//#include "timer.h"
|
||||||
ctrl_t *win_get_child(window_t *win, int x, int y)
|
ctrl_t *win_get_child(window_t *win, int x, int y)
|
||||||
|
Loading…
Reference in New Issue
Block a user