Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
小白菜888
Ffmpeg
提交
b45aceb6
F
Ffmpeg
项目概览
小白菜888
/
Ffmpeg
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
F
Ffmpeg
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
b45aceb6
编写于
3月 26, 2011
作者:
P
Philip Langdale
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Revert "CrystalHD: Improve interlaced h.264 support."
This reverts commit
e44073ca
.
上级
85b01098
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
83 addition
and
135 deletion
+83
-135
configure
configure
+1
-1
libavcodec/crystalhd.c
libavcodec/crystalhd.c
+82
-134
未找到文件。
configure
浏览文件 @
b45aceb6
...
...
@@ -1276,7 +1276,7 @@ h263_vaapi_hwaccel_select="vaapi h263_decoder"
h263i_decoder_select
=
"h263_decoder"
h263p_encoder_select
=
"h263_encoder"
h264_decoder_select
=
"golomb h264dsp h264pred"
h264_crystalhd_decoder_select
=
"crystalhd h264_mp4toannexb_bsf
h264_parser
"
h264_crystalhd_decoder_select
=
"crystalhd h264_mp4toannexb_bsf"
h264_dxva2_hwaccel_deps
=
"dxva2api_h"
h264_dxva2_hwaccel_select
=
"dxva2 h264_decoder"
h264_vaapi_hwaccel_select
=
"vaapi"
...
...
libavcodec/crystalhd.c
浏览文件 @
b45aceb6
/*
* - CrystalHD decoder module -
*
* Copyright(C) 2010
,2011
Philip Langdale <ffmpeg.philipl@overt.org>
* Copyright(C) 2010 Philip Langdale <ffmpeg.philipl@overt.org>
*
* This file is part of FFmpeg.
*
...
...
@@ -84,7 +84,6 @@
#include <libcrystalhd/libcrystalhd_if.h>
#include "avcodec.h"
#include "h264.h"
#include "libavutil/imgutils.h"
#include "libavutil/intreadwrite.h"
...
...
@@ -103,18 +102,16 @@
****************************************************************************/
typedef
enum
{
RET_ERROR
=
-
1
,
RET_OK
=
0
,
RET_COPY_AGAIN
=
1
,
RET_SKIP_NEXT_COPY
=
2
,
RET_COPY_NEXT_FIELD
=
3
,
RET_ERROR
=
-
1
,
RET_OK
=
0
,
RET_COPY_AGAIN
=
1
,
RET_SKIP_NEXT_COPY
=
2
,
}
CopyRet
;
typedef
struct
OpaqueList
{
struct
OpaqueList
*
next
;
uint64_t
fake_timestamp
;
uint64_t
reordered_opaque
;
uint8_t
pic_type
;
}
OpaqueList
;
typedef
struct
{
...
...
@@ -122,8 +119,6 @@ typedef struct {
AVFrame
pic
;
HANDLE
dev
;
AVCodecParserContext
*
parser
;
uint8_t
is_70012
;
uint8_t
*
sps_pps_buf
;
uint32_t
sps_pps_size
;
...
...
@@ -210,8 +205,7 @@ static inline void print_frame_info(CHDContext *priv, BC_DTS_PROC_OUT *output)
* OpaqueList functions
****************************************************************************/
static
uint64_t
opaque_list_push
(
CHDContext
*
priv
,
uint64_t
reordered_opaque
,
uint8_t
pic_type
)
static
uint64_t
opaque_list_push
(
CHDContext
*
priv
,
uint64_t
reordered_opaque
)
{
OpaqueList
*
newNode
=
av_mallocz
(
sizeof
(
OpaqueList
));
if
(
!
newNode
)
{
...
...
@@ -228,7 +222,6 @@ static uint64_t opaque_list_push(CHDContext *priv, uint64_t reordered_opaque,
}
priv
->
tail
=
newNode
;
newNode
->
reordered_opaque
=
reordered_opaque
;
newNode
->
pic_type
=
pic_type
;
return
newNode
->
fake_timestamp
;
}
...
...
@@ -238,15 +231,14 @@ static uint64_t opaque_list_push(CHDContext *priv, uint64_t reordered_opaque,
* in presentation order. If frames are reordered, this means we must be
* able to remove elements that are not the first element.
*/
static
uint8_t
opaque_list_pop
(
CHDContext
*
priv
,
uint64_t
fake_timestamp
,
uint64_t
*
reordered_opaque
,
uint8_t
*
pic_type
)
static
uint64_t
opaque_list_pop
(
CHDContext
*
priv
,
uint64_t
fake_timestamp
)
{
OpaqueList
*
node
=
priv
->
head
;
if
(
!
priv
->
head
)
{
av_log
(
priv
->
avctx
,
AV_LOG_ERROR
,
"CrystalHD: Attempted to query non-existent timestamps.
\n
"
);
return
FALS
E
;
return
AV_NOPTS_VALU
E
;
}
/*
...
...
@@ -254,15 +246,14 @@ static uint8_t opaque_list_pop(CHDContext *priv, uint64_t fake_timestamp,
* the head pointer rather than the previous element in the list.
*/
if
(
priv
->
head
->
fake_timestamp
==
fake_timestamp
)
{
*
reordered_opaque
=
node
->
reordered_opaque
;
*
pic_type
=
node
->
pic_type
;
uint64_t
reordered_opaque
=
node
->
reordered_opaque
;
priv
->
head
=
node
->
next
;
av_free
(
node
);
if
(
!
priv
->
head
->
next
)
priv
->
tail
=
priv
->
head
;
return
TRUE
;
return
reordered_opaque
;
}
/*
...
...
@@ -272,15 +263,14 @@ static uint8_t opaque_list_pop(CHDContext *priv, uint64_t fake_timestamp,
while
(
node
->
next
)
{
OpaqueList
*
next
=
node
->
next
;
if
(
next
->
fake_timestamp
==
fake_timestamp
)
{
*
reordered_opaque
=
node
->
reordered_opaque
;
*
pic_type
=
node
->
pic_type
;
uint64_t
reordered_opaque
=
next
->
reordered_opaque
;
node
->
next
=
next
->
next
;
av_free
(
next
);
if
(
!
node
->
next
)
priv
->
tail
=
node
;
return
TRUE
;
return
reordered_opaque
;
}
else
{
node
=
next
;
}
...
...
@@ -288,7 +278,7 @@ static uint8_t opaque_list_pop(CHDContext *priv, uint64_t fake_timestamp,
av_log
(
priv
->
avctx
,
AV_LOG_VERBOSE
,
"CrystalHD: Couldn't match fake_timestamp.
\n
"
);
return
FALS
E
;
return
AV_NOPTS_VALU
E
;
}
...
...
@@ -325,8 +315,6 @@ static av_cold int uninit(AVCodecContext *avctx)
DtsCloseDecoder
(
device
);
DtsDeviceClose
(
device
);
av_parser_close
(
priv
->
parser
);
av_free
(
priv
->
sps_pps_buf
);
if
(
priv
->
pic
.
data
[
0
])
...
...
@@ -489,13 +477,6 @@ static av_cold int init(AVCodecContext *avctx)
goto
fail
;
}
if
(
avctx
->
codec
->
id
==
CODEC_ID_H264
)
{
priv
->
parser
=
av_parser_init
(
avctx
->
codec
->
id
);
if
(
!
priv
->
parser
)
av_log
(
avctx
,
AV_LOG_WARNING
,
"Cannot open the h.264 parser! Interlaced h.264 content "
"will not be detected reliably.
\n
"
);
}
av_log
(
avctx
,
AV_LOG_VERBOSE
,
"CrystalHD: Init complete.
\n
"
);
return
0
;
...
...
@@ -511,24 +492,30 @@ static av_cold int init(AVCodecContext *avctx)
* us to distinguish between specific cases that require different handling.
* So, for now, we have to hard-code the behaviour we want.
*
* Specifically, there are PAFF samples where input is always separate fields
* but the hardware returns separate fields on one occasion and a field-pair
* on another. The code assumes the first case and define
* ASSUME_TWO_INPUTS_ONE_OUTPUT to assume the second case.
* The default behaviour is to assume MBAFF with input and output fieldpairs.
*
* Define ASSUME_PAFF_OVER_MBAFF to treat input as PAFF with separate input
* and output fields.
*
* Define ASSUME_TWO_INPUTS_ONE_OUTPUT to treat input as separate fields but
* output as a single fieldpair.
*
* Define both to mess up your playback.
*/
#define ASSUME_PAFF_OVER_MBAFF 0
#define ASSUME_TWO_INPUTS_ONE_OUTPUT 0
static
inline
CopyRet
copy_frame
(
AVCodecContext
*
avctx
,
BC_DTS_PROC_OUT
*
output
,
void
*
data
,
int
*
data_size
)
void
*
data
,
int
*
data_size
,
uint8_t
second_field
)
{
BC_STATUS
ret
;
BC_DTS_STATUS
decoder_status
;
uint8_t
ignore_interlaced
;
uint8_t
is_paff
;
uint8_t
next_frame_same
;
uint8_t
interlaced
;
CHDContext
*
priv
=
avctx
->
priv_data
;
int64_t
pkt_pts
=
AV_NOPTS_VALUE
;
uint8_t
pic_type
=
0
;
uint8_t
bottom_field
=
(
output
->
PicInfo
.
flags
&
VDEC_FLAG_BOTTOMFIELD
)
==
VDEC_FLAG_BOTTOMFIELD
;
...
...
@@ -542,27 +529,6 @@ static inline CopyRet copy_frame(AVCodecContext *avctx,
uint8_t
*
dst
;
int
dStride
;
if
(
output
->
PicInfo
.
timeStamp
!=
0
)
{
uint8_t
pop_ret
;
pop_ret
=
opaque_list_pop
(
priv
,
output
->
PicInfo
.
timeStamp
,
&
pkt_pts
,
&
pic_type
);
if
(
!
pop_ret
)
{
/*
* We will encounter a situation where a timestamp cannot be
* popped if a second field is being returned. In this case,
* each field has the same timestamp and the first one will
* cause it to be popped. To keep subsequent calculations
* simple, pic_type should be set a FIELD value - doesn't
* matter which, but I chose BOTTOM.
*/
pic_type
=
PICT_BOTTOM_FIELD
;
}
av_log
(
avctx
,
AV_LOG_VERBOSE
,
"output
\"
pts
\"
: %"
PRIu64
"
\n
"
,
output
->
PicInfo
.
timeStamp
);
av_log
(
avctx
,
AV_LOG_VERBOSE
,
"output picture type %d
\n
"
,
pic_type
);
}
ret
=
DtsGetDriverStatus
(
priv
->
dev
,
&
decoder_status
);
if
(
ret
!=
BC_STS_SUCCESS
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
...
...
@@ -570,19 +536,17 @@ static inline CopyRet copy_frame(AVCodecContext *avctx,
return
RET_ERROR
;
}
/*
* Testing has, so far, shown that we can't trust the interlaced flag for
* H.264 content when VDEC_FLAG_UNKNOWN_SRC is set.
*/
ignore_interlaced
=
avctx
->
codec
->
id
==
CODEC_ID_H264
&&
(
output
->
PicInfo
.
flags
&
VDEC_FLAG_UNKNOWN_SRC
)
&&
(
pic_type
==
0
||
pic_type
==
PICT_FRAME
||
ASSUME_TWO_INPUTS_ONE_OUTPUT
);
interlaced
=
(
output
->
PicInfo
.
flags
&
VDEC_FLAG_INTERLACED_SRC
)
&&
!
ignore_interlaced
;
is_paff
=
ASSUME_PAFF_OVER_MBAFF
||
!
(
output
->
PicInfo
.
flags
&
VDEC_FLAG_UNKNOWN_SRC
);
next_frame_same
=
output
->
PicInfo
.
picture_number
==
(
decoder_status
.
picNumFlags
&
~
0x40000000
);
interlaced
=
((
output
->
PicInfo
.
flags
&
VDEC_FLAG_INTERLACED_SRC
)
&&
is_paff
)
||
next_frame_same
||
bottom_field
||
second_field
;
av_log
(
avctx
,
AV_LOG_VERBOSE
,
"Interlaced state: %d | ignore_interlaced %d
\n
"
,
interlaced
,
ignore_interlaced
);
av_log
(
avctx
,
AV_LOG_VERBOSE
,
"CrystalHD: next_frame_same: %u | %u | %u
\n
"
,
next_frame_same
,
output
->
PicInfo
.
picture_number
,
decoder_status
.
picNumFlags
&
~
0x40000000
);
if
(
priv
->
pic
.
data
[
0
]
&&
!
priv
->
need_second_field
)
avctx
->
release_buffer
(
avctx
,
&
priv
->
pic
);
...
...
@@ -633,7 +597,8 @@ static inline CopyRet copy_frame(AVCodecContext *avctx,
for
(
sY
=
0
;
sY
<
height
;
dY
++
,
sY
++
)
{
memcpy
(
&
(
dst
[
dY
*
dStride
]),
&
(
src
[
sY
*
sStride
]),
bwidth
);
dY
++
;
if
(
interlaced
)
dY
++
;
}
}
else
{
av_image_copy_plane
(
dst
,
dStride
,
src
,
sStride
,
bwidth
,
height
);
...
...
@@ -643,7 +608,11 @@ static inline CopyRet copy_frame(AVCodecContext *avctx,
if
(
interlaced
)
priv
->
pic
.
top_field_first
=
!
bottom_first
;
priv
->
pic
.
pkt_pts
=
pkt_pts
;
if
(
output
->
PicInfo
.
timeStamp
!=
0
)
{
priv
->
pic
.
pkt_pts
=
opaque_list_pop
(
priv
,
output
->
PicInfo
.
timeStamp
);
av_log
(
avctx
,
AV_LOG_VERBOSE
,
"output
\"
pts
\"
: %"
PRIu64
"
\n
"
,
priv
->
pic
.
pkt_pts
);
}
if
(
!
priv
->
need_second_field
)
{
*
data_size
=
sizeof
(
AVFrame
);
...
...
@@ -656,18 +625,13 @@ static inline CopyRet copy_frame(AVCodecContext *avctx,
return
RET_SKIP_NEXT_COPY
;
}
/*
* Testing has shown that in all cases where we don't want to return the
* full frame immediately, VDEC_FLAG_UNKNOWN_SRC is set.
*/
return
priv
->
need_second_field
&&
!
(
output
->
PicInfo
.
flags
&
VDEC_FLAG_UNKNOWN_SRC
)
?
RET_COPY_NEXT_FIELD
:
RET_OK
;
return
RET_OK
;
}
static
inline
CopyRet
receive_frame
(
AVCodecContext
*
avctx
,
void
*
data
,
int
*
data_size
)
void
*
data
,
int
*
data_size
,
uint8_t
second_field
)
{
BC_STATUS
ret
;
BC_DTS_PROC_OUT
output
=
{
...
...
@@ -724,7 +688,7 @@ static inline CopyRet receive_frame(AVCodecContext *avctx,
priv
->
last_picture
=
output
.
PicInfo
.
picture_number
-
1
;
}
copy_ret
=
copy_frame
(
avctx
,
&
output
,
data
,
data_size
);
copy_ret
=
copy_frame
(
avctx
,
&
output
,
data
,
data_size
,
second_field
);
if
(
*
data_size
>
0
)
{
avctx
->
has_b_frames
--
;
priv
->
last_picture
++
;
...
...
@@ -760,29 +724,11 @@ static int decode(AVCodecContext *avctx, void *data, int *data_size, AVPacket *a
CHDContext
*
priv
=
avctx
->
priv_data
;
HANDLE
dev
=
priv
->
dev
;
int
len
=
avpkt
->
size
;
uint8_t
pic_type
=
0
;
av_log
(
avctx
,
AV_LOG_VERBOSE
,
"CrystalHD: decode_frame
\n
"
);
if
(
len
)
{
int32_t
tx_free
=
(
int32_t
)
DtsTxFreeSize
(
dev
);
if
(
priv
->
parser
)
{
uint8_t
*
pout
=
NULL
;
int
psize
=
len
;
H264Context
*
h
=
priv
->
parser
->
priv_data
;
while
(
psize
)
{
ret
=
av_parser_parse2
(
priv
->
parser
,
avctx
,
&
pout
,
&
psize
,
avpkt
->
data
,
len
,
avctx
->
pkt
->
pts
,
avctx
->
pkt
->
dts
,
len
-
psize
);
}
av_log
(
avctx
,
AV_LOG_VERBOSE
,
"CrystalHD: parser picture type %d
\n
"
,
h
->
s
.
picture_structure
);
pic_type
=
h
->
s
.
picture_structure
;
}
if
(
len
<
tx_free
-
1024
)
{
/*
* Despite being notionally opaque, either libcrystalhd or
...
...
@@ -793,7 +739,7 @@ static int decode(AVCodecContext *avctx, void *data, int *data_size, AVPacket *a
* avoiding mangling so we need to build a mapping to values
* we know will not be mangled.
*/
uint64_t
pts
=
opaque_list_push
(
priv
,
avctx
->
pkt
->
pts
,
pic_type
);
uint64_t
pts
=
opaque_list_push
(
priv
,
avctx
->
pkt
->
pts
);
if
(
!
pts
)
{
return
AVERROR
(
ENOMEM
);
}
...
...
@@ -860,39 +806,41 @@ static int decode(AVCodecContext *avctx, void *data, int *data_size, AVPacket *a
}
do
{
rec_ret
=
receive_frame
(
avctx
,
data
,
data_size
);
if
(
rec_ret
==
RET_OK
&&
*
data_size
==
0
)
{
/*
* This case is for when the encoded fields are stored
* separately and we get a separate avpkt for each one. To keep
* the pipeline stable, we should return nothing and wait for
* the next time round to grab the second field.
* H.264 PAFF is an example of this.
*/
av_log
(
avctx
,
AV_LOG_VERBOSE
,
"Returning after first field.
\n
"
);
avctx
->
has_b_frames
--
;
}
else
if
(
rec_ret
==
RET_COPY_NEXT_FIELD
)
{
/*
* This case is for when the encoded fields are stored in a
* single avpkt but the hardware returns then separately. Unless
* we grab the second field before returning, we'll slip another
* frame in the pipeline and if that happens a lot, we're sunk.
* So we have to get that second field now.
* Interlaced mpeg2 and vc1 are examples of this.
*/
av_log
(
avctx
,
AV_LOG_VERBOSE
,
"Trying to get second field.
\n
"
);
while
(
1
)
{
usleep
(
priv
->
decode_wait
);
ret
=
DtsGetDriverStatus
(
dev
,
&
decoder_status
);
if
(
ret
==
BC_STS_SUCCESS
&&
decoder_status
.
ReadyListCount
>
0
)
{
rec_ret
=
receive_frame
(
avctx
,
data
,
data_size
);
if
((
rec_ret
==
RET_OK
&&
*
data_size
>
0
)
||
rec_ret
==
RET_ERROR
)
break
;
rec_ret
=
receive_frame
(
avctx
,
data
,
data_size
,
0
);
if
(
rec_ret
==
0
&&
*
data_size
==
0
)
{
if
(
avctx
->
codec
->
id
==
CODEC_ID_H264
)
{
/*
* This case is for when the encoded fields are stored
* separately and we get a separate avpkt for each one. To keep
* the pipeline stable, we should return nothing and wait for
* the next time round to grab the second field.
* H.264 PAFF is an example of this.
*/
av_log
(
avctx
,
AV_LOG_VERBOSE
,
"Returning after first field.
\n
"
);
avctx
->
has_b_frames
--
;
}
else
{
/*
* This case is for when the encoded fields are stored in a
* single avpkt but the hardware returns then separately. Unless
* we grab the second field before returning, we'll slip another
* frame in the pipeline and if that happens a lot, we're sunk.
* So we have to get that second field now.
* Interlaced mpeg2 and vc1 are examples of this.
*/
av_log
(
avctx
,
AV_LOG_VERBOSE
,
"Trying to get second field.
\n
"
);
while
(
1
)
{
usleep
(
priv
->
decode_wait
);
ret
=
DtsGetDriverStatus
(
dev
,
&
decoder_status
);
if
(
ret
==
BC_STS_SUCCESS
&&
decoder_status
.
ReadyListCount
>
0
)
{
rec_ret
=
receive_frame
(
avctx
,
data
,
data_size
,
1
);
if
((
rec_ret
==
0
&&
*
data_size
>
0
)
||
rec_ret
==
RET_ERROR
)
break
;
}
}
av_log
(
avctx
,
AV_LOG_VERBOSE
,
"CrystalHD: Got second field.
\n
"
);
}
av_log
(
avctx
,
AV_LOG_VERBOSE
,
"CrystalHD: Got second field.
\n
"
);
}
else
if
(
rec_ret
==
RET_SKIP_NEXT_COPY
)
{
/*
* Two input packets got turned into a field pair. Gawd.
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录