Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
F
ffmpeg.wasm-core
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Linshizhi
ffmpeg.wasm-core
Commits
d724fe66
Commit
d724fe66
authored
Mar 18, 2012
by
Diego Biurrun
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dv: Split off DV video decoder into its own file.
parent
9f43fdda
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
442 additions
and
397 deletions
+442
-397
Makefile
libavcodec/Makefile
+1
-1
dv.c
libavcodec/dv.c
+8
-395
dv_tablegen.h
libavcodec/dv_tablegen.h
+3
-1
dvdata.h
libavcodec/dvdata.h
+44
-0
dvdec.c
libavcodec/dvdec.c
+386
-0
No files found.
libavcodec/Makefile
View file @
d724fe66
...
...
@@ -126,7 +126,7 @@ OBJS-$(CONFIG_DVBSUB_DECODER) += dvbsubdec.o
OBJS-$(CONFIG_DVBSUB_ENCODER)
+=
dvbsub.o
OBJS-$(CONFIG_DVDSUB_DECODER)
+=
dvdsubdec.o
OBJS-$(CONFIG_DVDSUB_ENCODER)
+=
dvdsubenc.o
OBJS-$(CONFIG_DVVIDEO_DECODER)
+=
dv.o
dvdata.o
OBJS-$(CONFIG_DVVIDEO_DECODER)
+=
dv
dec.o
dv
.o
dvdata.o
OBJS-$(CONFIG_DVVIDEO_ENCODER)
+=
dv.o
dvdata.o
OBJS-$(CONFIG_DXA_DECODER)
+=
dxa.o
OBJS-$(CONFIG_DXTORY_DECODER)
+=
dxtory.o
...
...
libavcodec/dv.c
View file @
d724fe66
...
...
@@ -49,37 +49,8 @@
#include "dvquant.h"
#include "dv_tablegen.h"
//#undef NDEBUG
//#include <assert.h>
typedef
struct
DVVideoContext
{
const
DVprofile
*
sys
;
AVFrame
picture
;
AVCodecContext
*
avctx
;
uint8_t
*
buf
;
uint8_t
dv_zigzag
[
2
][
64
];
void
(
*
get_pixels
)(
DCTELEM
*
block
,
const
uint8_t
*
pixels
,
int
line_size
);
void
(
*
fdct
[
2
])(
DCTELEM
*
block
);
void
(
*
idct_put
[
2
])(
uint8_t
*
dest
,
int
line_size
,
DCTELEM
*
block
);
me_cmp_func
ildct_cmp
;
}
DVVideoContext
;
#define TEX_VLC_BITS 9
/* XXX: also include quantization */
static
RL_VLC_ELEM
dv_rl_vlc
[
1184
];
static
inline
int
dv_work_pool_size
(
const
DVprofile
*
d
)
{
int
size
=
d
->
n_difchan
*
d
->
difseg_size
*
27
;
if
(
DV_PROFILE_IS_1080i50
(
d
))
size
-=
3
*
27
;
if
(
DV_PROFILE_IS_720p50
(
d
))
size
-=
4
*
27
;
return
size
;
}
RL_VLC_ELEM
ff_dv_rl_vlc
[
1184
];
static
inline
void
dv_calc_mb_coordinates
(
const
DVprofile
*
d
,
int
chan
,
int
seq
,
int
slot
,
uint16_t
*
tbl
)
...
...
@@ -196,7 +167,7 @@ static inline void dv_calc_mb_coordinates(const DVprofile *d, int chan, int seq,
}
}
static
int
dv_init_dynamic_tables
(
const
DVprofile
*
d
)
int
ff_
dv_init_dynamic_tables
(
const
DVprofile
*
d
)
{
int
j
,
i
,
c
,
s
,
p
;
uint32_t
*
factor1
,
*
factor2
;
...
...
@@ -257,7 +228,7 @@ static int dv_init_dynamic_tables(const DVprofile *d)
return
0
;
}
static
av_cold
int
dvvideo_init
(
AVCodecContext
*
avctx
)
av_cold
int
ff_
dvvideo_init
(
AVCodecContext
*
avctx
)
{
DVVideoContext
*
s
=
avctx
->
priv_data
;
DSPContext
dsp
;
...
...
@@ -310,9 +281,9 @@ static av_cold int dvvideo_init(AVCodecContext *avctx)
run
=
new_dv_vlc_run
[
code
]
+
1
;
level
=
new_dv_vlc_level
[
code
];
}
dv_rl_vlc
[
i
].
len
=
len
;
dv_rl_vlc
[
i
].
level
=
level
;
dv_rl_vlc
[
i
].
run
=
run
;
ff_
dv_rl_vlc
[
i
].
len
=
len
;
ff_
dv_rl_vlc
[
i
].
level
=
level
;
ff_
dv_rl_vlc
[
i
].
run
=
run
;
}
ff_free_vlc
(
&
dv_vlc
);
...
...
@@ -357,19 +328,9 @@ static av_cold int dvvideo_init_encoder(AVCodecContext *avctx)
return
-
1
;
}
return
dvvideo_init
(
avctx
);
return
ff_
dvvideo_init
(
avctx
);
}
typedef
struct
BlockInfo
{
const
uint32_t
*
factor_table
;
const
uint8_t
*
scan_table
;
uint8_t
pos
;
/* position in block */
void
(
*
idct_put
)(
uint8_t
*
dest
,
int
line_size
,
DCTELEM
*
block
);
uint8_t
partial_bit_count
;
uint32_t
partial_bit_buffer
;
int
shift_offset
;
}
BlockInfo
;
/* bit budget for AC only in 5 MBs */
static
const
int
vs_total_ac_bits
=
(
100
*
4
+
68
*
2
)
*
5
;
static
const
int
mb_area_start
[
5
]
=
{
1
,
6
,
21
,
43
,
64
};
...
...
@@ -379,268 +340,6 @@ static inline int put_bits_left(PutBitContext* s)
return
(
s
->
buf_end
-
s
->
buf
)
*
8
-
put_bits_count
(
s
);
}
/* decode AC coefficients */
static
void
dv_decode_ac
(
GetBitContext
*
gb
,
BlockInfo
*
mb
,
DCTELEM
*
block
)
{
int
last_index
=
gb
->
size_in_bits
;
const
uint8_t
*
scan_table
=
mb
->
scan_table
;
const
uint32_t
*
factor_table
=
mb
->
factor_table
;
int
pos
=
mb
->
pos
;
int
partial_bit_count
=
mb
->
partial_bit_count
;
int
level
,
run
,
vlc_len
,
index
;
OPEN_READER
(
re
,
gb
);
UPDATE_CACHE
(
re
,
gb
);
/* if we must parse a partial VLC, we do it here */
if
(
partial_bit_count
>
0
)
{
re_cache
=
re_cache
>>
partial_bit_count
|
mb
->
partial_bit_buffer
;
re_index
-=
partial_bit_count
;
mb
->
partial_bit_count
=
0
;
}
/* get the AC coefficients until last_index is reached */
for
(;;)
{
av_dlog
(
NULL
,
"%2d: bits=%04x index=%d
\n
"
,
pos
,
SHOW_UBITS
(
re
,
gb
,
16
),
re_index
);
/* our own optimized GET_RL_VLC */
index
=
NEG_USR32
(
re_cache
,
TEX_VLC_BITS
);
vlc_len
=
dv_rl_vlc
[
index
].
len
;
if
(
vlc_len
<
0
)
{
index
=
NEG_USR32
((
unsigned
)
re_cache
<<
TEX_VLC_BITS
,
-
vlc_len
)
+
dv_rl_vlc
[
index
].
level
;
vlc_len
=
TEX_VLC_BITS
-
vlc_len
;
}
level
=
dv_rl_vlc
[
index
].
level
;
run
=
dv_rl_vlc
[
index
].
run
;
/* gotta check if we're still within gb boundaries */
if
(
re_index
+
vlc_len
>
last_index
)
{
/* should be < 16 bits otherwise a codeword could have been parsed */
mb
->
partial_bit_count
=
last_index
-
re_index
;
mb
->
partial_bit_buffer
=
re_cache
&
~
(
-
1u
>>
mb
->
partial_bit_count
);
re_index
=
last_index
;
break
;
}
re_index
+=
vlc_len
;
av_dlog
(
NULL
,
"run=%d level=%d
\n
"
,
run
,
level
);
pos
+=
run
;
if
(
pos
>=
64
)
break
;
level
=
(
level
*
factor_table
[
pos
]
+
(
1
<<
(
dv_iweight_bits
-
1
)))
>>
dv_iweight_bits
;
block
[
scan_table
[
pos
]]
=
level
;
UPDATE_CACHE
(
re
,
gb
);
}
CLOSE_READER
(
re
,
gb
);
mb
->
pos
=
pos
;
}
static
inline
void
bit_copy
(
PutBitContext
*
pb
,
GetBitContext
*
gb
)
{
int
bits_left
=
get_bits_left
(
gb
);
while
(
bits_left
>=
MIN_CACHE_BITS
)
{
put_bits
(
pb
,
MIN_CACHE_BITS
,
get_bits
(
gb
,
MIN_CACHE_BITS
));
bits_left
-=
MIN_CACHE_BITS
;
}
if
(
bits_left
>
0
)
{
put_bits
(
pb
,
bits_left
,
get_bits
(
gb
,
bits_left
));
}
}
static
inline
void
dv_calculate_mb_xy
(
DVVideoContext
*
s
,
DVwork_chunk
*
work_chunk
,
int
m
,
int
*
mb_x
,
int
*
mb_y
)
{
*
mb_x
=
work_chunk
->
mb_coordinates
[
m
]
&
0xff
;
*
mb_y
=
work_chunk
->
mb_coordinates
[
m
]
>>
8
;
/* We work with 720p frames split in half. The odd half-frame (chan==2,3) is displaced :-( */
if
(
s
->
sys
->
height
==
720
&&
!
(
s
->
buf
[
1
]
&
0x0C
))
{
*
mb_y
-=
(
*
mb_y
>
17
)
?
18
:-
72
;
/* shifting the Y coordinate down by 72/2 macro blocks */
}
}
/* mb_x and mb_y are in units of 8 pixels */
static
int
dv_decode_video_segment
(
AVCodecContext
*
avctx
,
void
*
arg
)
{
DVVideoContext
*
s
=
avctx
->
priv_data
;
DVwork_chunk
*
work_chunk
=
arg
;
int
quant
,
dc
,
dct_mode
,
class1
,
j
;
int
mb_index
,
mb_x
,
mb_y
,
last_index
;
int
y_stride
,
linesize
;
DCTELEM
*
block
,
*
block1
;
int
c_offset
;
uint8_t
*
y_ptr
;
const
uint8_t
*
buf_ptr
;
PutBitContext
pb
,
vs_pb
;
GetBitContext
gb
;
BlockInfo
mb_data
[
5
*
DV_MAX_BPM
],
*
mb
,
*
mb1
;
LOCAL_ALIGNED_16
(
DCTELEM
,
sblock
,
[
5
*
DV_MAX_BPM
],
[
64
]);
LOCAL_ALIGNED_16
(
uint8_t
,
mb_bit_buffer
,
[
80
+
FF_INPUT_BUFFER_PADDING_SIZE
]);
/* allow some slack */
LOCAL_ALIGNED_16
(
uint8_t
,
vs_bit_buffer
,
[
5
*
80
+
FF_INPUT_BUFFER_PADDING_SIZE
]);
/* allow some slack */
const
int
log2_blocksize
=
3
-
s
->
avctx
->
lowres
;
int
is_field_mode
[
5
];
assert
((((
int
)
mb_bit_buffer
)
&
7
)
==
0
);
assert
((((
int
)
vs_bit_buffer
)
&
7
)
==
0
);
memset
(
sblock
,
0
,
5
*
DV_MAX_BPM
*
sizeof
(
*
sblock
));
/* pass 1: read DC and AC coefficients in blocks */
buf_ptr
=
&
s
->
buf
[
work_chunk
->
buf_offset
*
80
];
block1
=
&
sblock
[
0
][
0
];
mb1
=
mb_data
;
init_put_bits
(
&
vs_pb
,
vs_bit_buffer
,
5
*
80
);
for
(
mb_index
=
0
;
mb_index
<
5
;
mb_index
++
,
mb1
+=
s
->
sys
->
bpm
,
block1
+=
s
->
sys
->
bpm
*
64
)
{
/* skip header */
quant
=
buf_ptr
[
3
]
&
0x0f
;
buf_ptr
+=
4
;
init_put_bits
(
&
pb
,
mb_bit_buffer
,
80
);
mb
=
mb1
;
block
=
block1
;
is_field_mode
[
mb_index
]
=
0
;
for
(
j
=
0
;
j
<
s
->
sys
->
bpm
;
j
++
)
{
last_index
=
s
->
sys
->
block_sizes
[
j
];
init_get_bits
(
&
gb
,
buf_ptr
,
last_index
);
/* get the DC */
dc
=
get_sbits
(
&
gb
,
9
);
dct_mode
=
get_bits1
(
&
gb
);
class1
=
get_bits
(
&
gb
,
2
);
if
(
DV_PROFILE_IS_HD
(
s
->
sys
))
{
mb
->
idct_put
=
s
->
idct_put
[
0
];
mb
->
scan_table
=
s
->
dv_zigzag
[
0
];
mb
->
factor_table
=
&
s
->
sys
->
idct_factor
[(
j
>=
4
)
*
4
*
16
*
64
+
class1
*
16
*
64
+
quant
*
64
];
is_field_mode
[
mb_index
]
|=
!
j
&&
dct_mode
;
}
else
{
mb
->
idct_put
=
s
->
idct_put
[
dct_mode
&&
log2_blocksize
==
3
];
mb
->
scan_table
=
s
->
dv_zigzag
[
dct_mode
];
mb
->
factor_table
=
&
s
->
sys
->
idct_factor
[(
class1
==
3
)
*
2
*
22
*
64
+
dct_mode
*
22
*
64
+
(
quant
+
dv_quant_offset
[
class1
])
*
64
];
}
dc
=
dc
<<
2
;
/* convert to unsigned because 128 is not added in the
standard IDCT */
dc
+=
1024
;
block
[
0
]
=
dc
;
buf_ptr
+=
last_index
>>
3
;
mb
->
pos
=
0
;
mb
->
partial_bit_count
=
0
;
av_dlog
(
avctx
,
"MB block: %d, %d "
,
mb_index
,
j
);
dv_decode_ac
(
&
gb
,
mb
,
block
);
/* write the remaining bits in a new buffer only if the
block is finished */
if
(
mb
->
pos
>=
64
)
bit_copy
(
&
pb
,
&
gb
);
block
+=
64
;
mb
++
;
}
/* pass 2: we can do it just after */
av_dlog
(
avctx
,
"***pass 2 size=%d MB#=%d
\n
"
,
put_bits_count
(
&
pb
),
mb_index
);
block
=
block1
;
mb
=
mb1
;
init_get_bits
(
&
gb
,
mb_bit_buffer
,
put_bits_count
(
&
pb
));
put_bits32
(
&
pb
,
0
);
// padding must be zeroed
flush_put_bits
(
&
pb
);
for
(
j
=
0
;
j
<
s
->
sys
->
bpm
;
j
++
,
block
+=
64
,
mb
++
)
{
if
(
mb
->
pos
<
64
&&
get_bits_left
(
&
gb
)
>
0
)
{
dv_decode_ac
(
&
gb
,
mb
,
block
);
/* if still not finished, no need to parse other blocks */
if
(
mb
->
pos
<
64
)
break
;
}
}
/* all blocks are finished, so the extra bytes can be used at
the video segment level */
if
(
j
>=
s
->
sys
->
bpm
)
bit_copy
(
&
vs_pb
,
&
gb
);
}
/* we need a pass over the whole video segment */
av_dlog
(
avctx
,
"***pass 3 size=%d
\n
"
,
put_bits_count
(
&
vs_pb
));
block
=
&
sblock
[
0
][
0
];
mb
=
mb_data
;
init_get_bits
(
&
gb
,
vs_bit_buffer
,
put_bits_count
(
&
vs_pb
));
put_bits32
(
&
vs_pb
,
0
);
// padding must be zeroed
flush_put_bits
(
&
vs_pb
);
for
(
mb_index
=
0
;
mb_index
<
5
;
mb_index
++
)
{
for
(
j
=
0
;
j
<
s
->
sys
->
bpm
;
j
++
)
{
if
(
mb
->
pos
<
64
)
{
av_dlog
(
avctx
,
"start %d:%d
\n
"
,
mb_index
,
j
);
dv_decode_ac
(
&
gb
,
mb
,
block
);
}
if
(
mb
->
pos
>=
64
&&
mb
->
pos
<
127
)
av_log
(
avctx
,
AV_LOG_ERROR
,
"AC EOB marker is absent pos=%d
\n
"
,
mb
->
pos
);
block
+=
64
;
mb
++
;
}
}
/* compute idct and place blocks */
block
=
&
sblock
[
0
][
0
];
mb
=
mb_data
;
for
(
mb_index
=
0
;
mb_index
<
5
;
mb_index
++
)
{
dv_calculate_mb_xy
(
s
,
work_chunk
,
mb_index
,
&
mb_x
,
&
mb_y
);
/* idct_put'ting luminance */
if
((
s
->
sys
->
pix_fmt
==
PIX_FMT_YUV420P
)
||
(
s
->
sys
->
pix_fmt
==
PIX_FMT_YUV411P
&&
mb_x
>=
(
704
/
8
))
||
(
s
->
sys
->
height
>=
720
&&
mb_y
!=
134
))
{
y_stride
=
(
s
->
picture
.
linesize
[
0
]
<<
((
!
is_field_mode
[
mb_index
])
*
log2_blocksize
));
}
else
{
y_stride
=
(
2
<<
log2_blocksize
);
}
y_ptr
=
s
->
picture
.
data
[
0
]
+
((
mb_y
*
s
->
picture
.
linesize
[
0
]
+
mb_x
)
<<
log2_blocksize
);
linesize
=
s
->
picture
.
linesize
[
0
]
<<
is_field_mode
[
mb_index
];
mb
[
0
]
.
idct_put
(
y_ptr
,
linesize
,
block
+
0
*
64
);
if
(
s
->
sys
->
video_stype
==
4
)
{
/* SD 422 */
mb
[
2
].
idct_put
(
y_ptr
+
(
1
<<
log2_blocksize
)
,
linesize
,
block
+
2
*
64
);
}
else
{
mb
[
1
].
idct_put
(
y_ptr
+
(
1
<<
log2_blocksize
)
,
linesize
,
block
+
1
*
64
);
mb
[
2
].
idct_put
(
y_ptr
+
y_stride
,
linesize
,
block
+
2
*
64
);
mb
[
3
].
idct_put
(
y_ptr
+
(
1
<<
log2_blocksize
)
+
y_stride
,
linesize
,
block
+
3
*
64
);
}
mb
+=
4
;
block
+=
4
*
64
;
/* idct_put'ting chrominance */
c_offset
=
(((
mb_y
>>
(
s
->
sys
->
pix_fmt
==
PIX_FMT_YUV420P
))
*
s
->
picture
.
linesize
[
1
]
+
(
mb_x
>>
((
s
->
sys
->
pix_fmt
==
PIX_FMT_YUV411P
)
?
2
:
1
)))
<<
log2_blocksize
);
for
(
j
=
2
;
j
;
j
--
)
{
uint8_t
*
c_ptr
=
s
->
picture
.
data
[
j
]
+
c_offset
;
if
(
s
->
sys
->
pix_fmt
==
PIX_FMT_YUV411P
&&
mb_x
>=
(
704
/
8
))
{
uint64_t
aligned_pixels
[
64
/
8
];
uint8_t
*
pixels
=
(
uint8_t
*
)
aligned_pixels
;
uint8_t
*
c_ptr1
,
*
ptr1
;
int
x
,
y
;
mb
->
idct_put
(
pixels
,
8
,
block
);
for
(
y
=
0
;
y
<
(
1
<<
log2_blocksize
);
y
++
,
c_ptr
+=
s
->
picture
.
linesize
[
j
],
pixels
+=
8
)
{
ptr1
=
pixels
+
(
1
<<
(
log2_blocksize
-
1
));
c_ptr1
=
c_ptr
+
(
s
->
picture
.
linesize
[
j
]
<<
log2_blocksize
);
for
(
x
=
0
;
x
<
(
1
<<
(
log2_blocksize
-
1
));
x
++
)
{
c_ptr
[
x
]
=
pixels
[
x
];
c_ptr1
[
x
]
=
ptr1
[
x
];
}
}
block
+=
64
;
mb
++
;
}
else
{
y_stride
=
(
mb_y
==
134
)
?
(
1
<<
log2_blocksize
)
:
s
->
picture
.
linesize
[
j
]
<<
((
!
is_field_mode
[
mb_index
])
*
log2_blocksize
);
linesize
=
s
->
picture
.
linesize
[
j
]
<<
is_field_mode
[
mb_index
];
(
mb
++
)
->
idct_put
(
c_ptr
,
linesize
,
block
);
block
+=
64
;
if
(
s
->
sys
->
bpm
==
8
)
{
(
mb
++
)
->
idct_put
(
c_ptr
+
y_stride
,
linesize
,
block
);
block
+=
64
;
}
}
}
}
return
0
;
}
#if CONFIG_SMALL
/* Converts run and level (where level != 0) pair into VLC, returning bit size */
static
av_always_inline
int
dv_rl2vlc
(
int
run
,
int
level
,
int
sign
,
uint32_t
*
vlc
)
...
...
@@ -1060,64 +759,6 @@ static int dv_encode_video_segment(AVCodecContext *avctx, void *arg)
return
0
;
}
#if CONFIG_DVVIDEO_DECODER
/* NOTE: exactly one frame must be given (120000 bytes for NTSC,
144000 bytes for PAL - or twice those for 50Mbps) */
static
int
dvvideo_decode_frame
(
AVCodecContext
*
avctx
,
void
*
data
,
int
*
data_size
,
AVPacket
*
avpkt
)
{
const
uint8_t
*
buf
=
avpkt
->
data
;
int
buf_size
=
avpkt
->
size
;
DVVideoContext
*
s
=
avctx
->
priv_data
;
const
uint8_t
*
vsc_pack
;
int
apt
,
is16_9
;
s
->
sys
=
avpriv_dv_frame_profile
(
s
->
sys
,
buf
,
buf_size
);
if
(
!
s
->
sys
||
buf_size
<
s
->
sys
->
frame_size
||
dv_init_dynamic_tables
(
s
->
sys
))
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"could not find dv frame profile
\n
"
);
return
-
1
;
/* NOTE: we only accept several full frames */
}
if
(
s
->
picture
.
data
[
0
])
avctx
->
release_buffer
(
avctx
,
&
s
->
picture
);
s
->
picture
.
reference
=
0
;
s
->
picture
.
key_frame
=
1
;
s
->
picture
.
pict_type
=
AV_PICTURE_TYPE_I
;
avctx
->
pix_fmt
=
s
->
sys
->
pix_fmt
;
avctx
->
time_base
=
s
->
sys
->
time_base
;
avcodec_set_dimensions
(
avctx
,
s
->
sys
->
width
,
s
->
sys
->
height
);
if
(
avctx
->
get_buffer
(
avctx
,
&
s
->
picture
)
<
0
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"get_buffer() failed
\n
"
);
return
-
1
;
}
s
->
picture
.
interlaced_frame
=
1
;
s
->
picture
.
top_field_first
=
0
;
s
->
buf
=
buf
;
avctx
->
execute
(
avctx
,
dv_decode_video_segment
,
s
->
sys
->
work_chunks
,
NULL
,
dv_work_pool_size
(
s
->
sys
),
sizeof
(
DVwork_chunk
));
emms_c
();
/* return image */
*
data_size
=
sizeof
(
AVFrame
);
*
(
AVFrame
*
)
data
=
s
->
picture
;
/* Determine the codec's sample_aspect ratio from the packet */
vsc_pack
=
buf
+
80
*
5
+
48
+
5
;
if
(
*
vsc_pack
==
dv_video_control
)
{
apt
=
buf
[
4
]
&
0x07
;
is16_9
=
(
vsc_pack
&&
((
vsc_pack
[
2
]
&
0x07
)
==
0x02
||
(
!
apt
&&
(
vsc_pack
[
2
]
&
0x07
)
==
0x07
)));
avctx
->
sample_aspect_ratio
=
s
->
sys
->
sar
[
is16_9
];
}
return
s
->
sys
->
frame_size
;
}
#endif
/* CONFIG_DVVIDEO_DECODER */
static
inline
int
dv_write_pack
(
enum
dv_pack_type
pack_id
,
DVVideoContext
*
c
,
uint8_t
*
buf
)
{
...
...
@@ -1283,7 +924,7 @@ static int dvvideo_encode_frame(AVCodecContext *c, AVPacket *pkt,
int
ret
;
s
->
sys
=
avpriv_dv_codec_profile
(
c
);
if
(
!
s
->
sys
||
dv_init_dynamic_tables
(
s
->
sys
))
if
(
!
s
->
sys
||
ff_
dv_init_dynamic_tables
(
s
->
sys
))
return
-
1
;
if
((
ret
=
ff_alloc_packet
(
pkt
,
s
->
sys
->
frame_size
))
<
0
)
{
av_log
(
c
,
AV_LOG_ERROR
,
"Error getting output packet.
\n
"
);
...
...
@@ -1308,20 +949,7 @@ static int dvvideo_encode_frame(AVCodecContext *c, AVPacket *pkt,
return
0
;
}
#endif
static
int
dvvideo_close
(
AVCodecContext
*
c
)
{
DVVideoContext
*
s
=
c
->
priv_data
;
if
(
s
->
picture
.
data
[
0
])
c
->
release_buffer
(
c
,
&
s
->
picture
);
return
0
;
}
#if CONFIG_DVVIDEO_ENCODER
AVCodec
ff_dvvideo_encoder
=
{
.
name
=
"dvvideo"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
...
...
@@ -1334,18 +962,3 @@ AVCodec ff_dvvideo_encoder = {
.
long_name
=
NULL_IF_CONFIG_SMALL
(
"DV (Digital Video)"
),
};
#endif // CONFIG_DVVIDEO_ENCODER
#if CONFIG_DVVIDEO_DECODER
AVCodec
ff_dvvideo_decoder
=
{
.
name
=
"dvvideo"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
id
=
CODEC_ID_DVVIDEO
,
.
priv_data_size
=
sizeof
(
DVVideoContext
),
.
init
=
dvvideo_init
,
.
close
=
dvvideo_close
,
.
decode
=
dvvideo_decode_frame
,
.
capabilities
=
CODEC_CAP_DR1
|
CODEC_CAP_SLICE_THREADS
,
.
max_lowres
=
3
,
.
long_name
=
NULL_IF_CONFIG_SMALL
(
"DV (Digital Video)"
),
};
#endif
libavcodec/dv_tablegen.h
View file @
d724fe66
...
...
@@ -24,6 +24,8 @@
#define AVCODEC_DV_TABLEGEN_H
#include <stdint.h>
#include "libavutil/attributes.h"
#include "dv_vlc_data.h"
#if CONFIG_SMALL
...
...
@@ -46,7 +48,7 @@ typedef struct dv_vlc_pair {
#else
static
struct
dv_vlc_pair
dv_vlc_map
[
DV_VLC_MAP_RUN_SIZE
][
DV_VLC_MAP_LEV_SIZE
];
static
void
dv_vlc_map_tableinit
(
void
)
static
void
av_unused
dv_vlc_map_tableinit
(
void
)
{
int
i
,
j
;
for
(
i
=
0
;
i
<
NB_DV_VLC
-
1
;
i
++
)
{
...
...
libavcodec/dvdata.h
View file @
d724fe66
...
...
@@ -29,6 +29,8 @@
#include "libavutil/rational.h"
#include "avcodec.h"
#include "dsputil.h"
#include "get_bits.h"
typedef
struct
DVwork_chunk
{
uint16_t
buf_offset
;
...
...
@@ -65,6 +67,20 @@ typedef struct DVprofile {
const
uint8_t
(
*
audio_shuffle
)[
9
];
/* PCM shuffling table */
}
DVprofile
;
typedef
struct
DVVideoContext
{
const
DVprofile
*
sys
;
AVFrame
picture
;
AVCodecContext
*
avctx
;
uint8_t
*
buf
;
uint8_t
dv_zigzag
[
2
][
64
];
void
(
*
get_pixels
)(
DCTELEM
*
block
,
const
uint8_t
*
pixels
,
int
line_size
);
void
(
*
fdct
[
2
])(
DCTELEM
*
block
);
void
(
*
idct_put
[
2
])(
uint8_t
*
dest
,
int
line_size
,
DCTELEM
*
block
);
me_cmp_func
ildct_cmp
;
}
DVVideoContext
;
enum
dv_section_type
{
dv_sect_header
=
0x1f
,
dv_sect_subcode
=
0x3f
,
...
...
@@ -106,8 +122,36 @@ enum dv_pack_type {
*/
#define DV_MAX_BPM 8
#define TEX_VLC_BITS 9
extern
RL_VLC_ELEM
ff_dv_rl_vlc
[
1184
];
const
DVprofile
*
avpriv_dv_frame_profile
(
const
DVprofile
*
sys
,
const
uint8_t
*
frame
,
unsigned
buf_size
);
const
DVprofile
*
avpriv_dv_codec_profile
(
AVCodecContext
*
codec
);
int
ff_dv_init_dynamic_tables
(
const
DVprofile
*
d
);
int
ff_dvvideo_init
(
AVCodecContext
*
avctx
);
static
inline
int
dv_work_pool_size
(
const
DVprofile
*
d
)
{
int
size
=
d
->
n_difchan
*
d
->
difseg_size
*
27
;
if
(
DV_PROFILE_IS_1080i50
(
d
))
size
-=
3
*
27
;
if
(
DV_PROFILE_IS_720p50
(
d
))
size
-=
4
*
27
;
return
size
;
}
static
inline
void
dv_calculate_mb_xy
(
DVVideoContext
*
s
,
DVwork_chunk
*
work_chunk
,
int
m
,
int
*
mb_x
,
int
*
mb_y
)
{
*
mb_x
=
work_chunk
->
mb_coordinates
[
m
]
&
0xff
;
*
mb_y
=
work_chunk
->
mb_coordinates
[
m
]
>>
8
;
/* We work with 720p frames split in half. The odd half-frame (chan==2,3) is displaced :-( */
if
(
s
->
sys
->
height
==
720
&&
!
(
s
->
buf
[
1
]
&
0x0C
))
{
*
mb_y
-=
(
*
mb_y
>
17
)
?
18
:-
72
;
/* shifting the Y coordinate down by 72/2 macro blocks */
}
}
#endif
/* AVCODEC_DVDATA_H */
libavcodec/dvdec.c
0 → 100644
View file @
d724fe66
/*
* DV decoder
* Copyright (c) 2002 Fabrice Bellard
* Copyright (c) 2004 Roman Shaposhnik
*
* 50 Mbps (DVCPRO50) support
* Copyright (c) 2006 Daniel Maas <dmaas@maasdigital.com>
*
* 100 Mbps (DVCPRO HD) support
* Initial code by Daniel Maas <dmaas@maasdigital.com> (funded by BBC R&D)
* Final code by Roman Shaposhnik
*
* Many thanks to Dan Dennedy <dan@dennedy.org> for providing wealth
* of DV technical info.
*
* This file is part of Libav.
*
* Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Libav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* DV decoder
*/
#include "libavutil/pixdesc.h"
#include "avcodec.h"
#include "dsputil.h"
#include "get_bits.h"
#include "put_bits.h"
#include "simple_idct.h"
#include "dvdata.h"
#include "dvquant.h"
#include "dv_tablegen.h"
typedef
struct
BlockInfo
{
const
uint32_t
*
factor_table
;
const
uint8_t
*
scan_table
;
uint8_t
pos
;
/* position in block */
void
(
*
idct_put
)(
uint8_t
*
dest
,
int
line_size
,
DCTELEM
*
block
);
uint8_t
partial_bit_count
;
uint32_t
partial_bit_buffer
;
int
shift_offset
;
}
BlockInfo
;
/* decode AC coefficients */
static
void
dv_decode_ac
(
GetBitContext
*
gb
,
BlockInfo
*
mb
,
DCTELEM
*
block
)
{
int
last_index
=
gb
->
size_in_bits
;
const
uint8_t
*
scan_table
=
mb
->
scan_table
;
const
uint32_t
*
factor_table
=
mb
->
factor_table
;
int
pos
=
mb
->
pos
;
int
partial_bit_count
=
mb
->
partial_bit_count
;
int
level
,
run
,
vlc_len
,
index
;
OPEN_READER
(
re
,
gb
);
UPDATE_CACHE
(
re
,
gb
);
/* if we must parse a partial VLC, we do it here */
if
(
partial_bit_count
>
0
)
{
re_cache
=
re_cache
>>
partial_bit_count
|
mb
->
partial_bit_buffer
;
re_index
-=
partial_bit_count
;
mb
->
partial_bit_count
=
0
;
}
/* get the AC coefficients until last_index is reached */
for
(;;)
{
av_dlog
(
NULL
,
"%2d: bits=%04x index=%d
\n
"
,
pos
,
SHOW_UBITS
(
re
,
gb
,
16
),
re_index
);
/* our own optimized GET_RL_VLC */
index
=
NEG_USR32
(
re_cache
,
TEX_VLC_BITS
);
vlc_len
=
ff_dv_rl_vlc
[
index
].
len
;
if
(
vlc_len
<
0
)
{
index
=
NEG_USR32
((
unsigned
)
re_cache
<<
TEX_VLC_BITS
,
-
vlc_len
)
+
ff_dv_rl_vlc
[
index
].
level
;
vlc_len
=
TEX_VLC_BITS
-
vlc_len
;
}
level
=
ff_dv_rl_vlc
[
index
].
level
;
run
=
ff_dv_rl_vlc
[
index
].
run
;
/* gotta check if we're still within gb boundaries */
if
(
re_index
+
vlc_len
>
last_index
)
{
/* should be < 16 bits otherwise a codeword could have been parsed */
mb
->
partial_bit_count
=
last_index
-
re_index
;
mb
->
partial_bit_buffer
=
re_cache
&
~
(
-
1u
>>
mb
->
partial_bit_count
);
re_index
=
last_index
;
break
;
}
re_index
+=
vlc_len
;
av_dlog
(
NULL
,
"run=%d level=%d
\n
"
,
run
,
level
);
pos
+=
run
;
if
(
pos
>=
64
)
break
;
level
=
(
level
*
factor_table
[
pos
]
+
(
1
<<
(
dv_iweight_bits
-
1
)))
>>
dv_iweight_bits
;
block
[
scan_table
[
pos
]]
=
level
;
UPDATE_CACHE
(
re
,
gb
);
}
CLOSE_READER
(
re
,
gb
);
mb
->
pos
=
pos
;
}
static
inline
void
bit_copy
(
PutBitContext
*
pb
,
GetBitContext
*
gb
)
{
int
bits_left
=
get_bits_left
(
gb
);
while
(
bits_left
>=
MIN_CACHE_BITS
)
{
put_bits
(
pb
,
MIN_CACHE_BITS
,
get_bits
(
gb
,
MIN_CACHE_BITS
));
bits_left
-=
MIN_CACHE_BITS
;
}
if
(
bits_left
>
0
)
{
put_bits
(
pb
,
bits_left
,
get_bits
(
gb
,
bits_left
));
}
}
/* mb_x and mb_y are in units of 8 pixels */
static
int
dv_decode_video_segment
(
AVCodecContext
*
avctx
,
void
*
arg
)
{
DVVideoContext
*
s
=
avctx
->
priv_data
;
DVwork_chunk
*
work_chunk
=
arg
;
int
quant
,
dc
,
dct_mode
,
class1
,
j
;
int
mb_index
,
mb_x
,
mb_y
,
last_index
;
int
y_stride
,
linesize
;
DCTELEM
*
block
,
*
block1
;
int
c_offset
;
uint8_t
*
y_ptr
;
const
uint8_t
*
buf_ptr
;
PutBitContext
pb
,
vs_pb
;
GetBitContext
gb
;
BlockInfo
mb_data
[
5
*
DV_MAX_BPM
],
*
mb
,
*
mb1
;
LOCAL_ALIGNED_16
(
DCTELEM
,
sblock
,
[
5
*
DV_MAX_BPM
],
[
64
]);
LOCAL_ALIGNED_16
(
uint8_t
,
mb_bit_buffer
,
[
80
+
FF_INPUT_BUFFER_PADDING_SIZE
]);
/* allow some slack */
LOCAL_ALIGNED_16
(
uint8_t
,
vs_bit_buffer
,
[
5
*
80
+
FF_INPUT_BUFFER_PADDING_SIZE
]);
/* allow some slack */
const
int
log2_blocksize
=
3
-
s
->
avctx
->
lowres
;
int
is_field_mode
[
5
];
assert
((((
int
)
mb_bit_buffer
)
&
7
)
==
0
);
assert
((((
int
)
vs_bit_buffer
)
&
7
)
==
0
);
memset
(
sblock
,
0
,
5
*
DV_MAX_BPM
*
sizeof
(
*
sblock
));
/* pass 1: read DC and AC coefficients in blocks */
buf_ptr
=
&
s
->
buf
[
work_chunk
->
buf_offset
*
80
];
block1
=
&
sblock
[
0
][
0
];
mb1
=
mb_data
;
init_put_bits
(
&
vs_pb
,
vs_bit_buffer
,
5
*
80
);
for
(
mb_index
=
0
;
mb_index
<
5
;
mb_index
++
,
mb1
+=
s
->
sys
->
bpm
,
block1
+=
s
->
sys
->
bpm
*
64
)
{
/* skip header */
quant
=
buf_ptr
[
3
]
&
0x0f
;
buf_ptr
+=
4
;
init_put_bits
(
&
pb
,
mb_bit_buffer
,
80
);
mb
=
mb1
;
block
=
block1
;
is_field_mode
[
mb_index
]
=
0
;
for
(
j
=
0
;
j
<
s
->
sys
->
bpm
;
j
++
)
{
last_index
=
s
->
sys
->
block_sizes
[
j
];
init_get_bits
(
&
gb
,
buf_ptr
,
last_index
);
/* get the DC */
dc
=
get_sbits
(
&
gb
,
9
);
dct_mode
=
get_bits1
(
&
gb
);
class1
=
get_bits
(
&
gb
,
2
);
if
(
DV_PROFILE_IS_HD
(
s
->
sys
))
{
mb
->
idct_put
=
s
->
idct_put
[
0
];
mb
->
scan_table
=
s
->
dv_zigzag
[
0
];
mb
->
factor_table
=
&
s
->
sys
->
idct_factor
[(
j
>=
4
)
*
4
*
16
*
64
+
class1
*
16
*
64
+
quant
*
64
];
is_field_mode
[
mb_index
]
|=
!
j
&&
dct_mode
;
}
else
{
mb
->
idct_put
=
s
->
idct_put
[
dct_mode
&&
log2_blocksize
==
3
];
mb
->
scan_table
=
s
->
dv_zigzag
[
dct_mode
];
mb
->
factor_table
=
&
s
->
sys
->
idct_factor
[(
class1
==
3
)
*
2
*
22
*
64
+
dct_mode
*
22
*
64
+
(
quant
+
dv_quant_offset
[
class1
])
*
64
];
}
dc
=
dc
<<
2
;
/* convert to unsigned because 128 is not added in the
standard IDCT */
dc
+=
1024
;
block
[
0
]
=
dc
;
buf_ptr
+=
last_index
>>
3
;
mb
->
pos
=
0
;
mb
->
partial_bit_count
=
0
;
av_dlog
(
avctx
,
"MB block: %d, %d "
,
mb_index
,
j
);
dv_decode_ac
(
&
gb
,
mb
,
block
);
/* write the remaining bits in a new buffer only if the
block is finished */
if
(
mb
->
pos
>=
64
)
bit_copy
(
&
pb
,
&
gb
);
block
+=
64
;
mb
++
;
}
/* pass 2: we can do it just after */
av_dlog
(
avctx
,
"***pass 2 size=%d MB#=%d
\n
"
,
put_bits_count
(
&
pb
),
mb_index
);
block
=
block1
;
mb
=
mb1
;
init_get_bits
(
&
gb
,
mb_bit_buffer
,
put_bits_count
(
&
pb
));
put_bits32
(
&
pb
,
0
);
// padding must be zeroed
flush_put_bits
(
&
pb
);
for
(
j
=
0
;
j
<
s
->
sys
->
bpm
;
j
++
,
block
+=
64
,
mb
++
)
{
if
(
mb
->
pos
<
64
&&
get_bits_left
(
&
gb
)
>
0
)
{
dv_decode_ac
(
&
gb
,
mb
,
block
);
/* if still not finished, no need to parse other blocks */
if
(
mb
->
pos
<
64
)
break
;
}
}
/* all blocks are finished, so the extra bytes can be used at
the video segment level */
if
(
j
>=
s
->
sys
->
bpm
)
bit_copy
(
&
vs_pb
,
&
gb
);
}
/* we need a pass over the whole video segment */
av_dlog
(
avctx
,
"***pass 3 size=%d
\n
"
,
put_bits_count
(
&
vs_pb
));
block
=
&
sblock
[
0
][
0
];
mb
=
mb_data
;
init_get_bits
(
&
gb
,
vs_bit_buffer
,
put_bits_count
(
&
vs_pb
));
put_bits32
(
&
vs_pb
,
0
);
// padding must be zeroed
flush_put_bits
(
&
vs_pb
);
for
(
mb_index
=
0
;
mb_index
<
5
;
mb_index
++
)
{
for
(
j
=
0
;
j
<
s
->
sys
->
bpm
;
j
++
)
{
if
(
mb
->
pos
<
64
)
{
av_dlog
(
avctx
,
"start %d:%d
\n
"
,
mb_index
,
j
);
dv_decode_ac
(
&
gb
,
mb
,
block
);
}
if
(
mb
->
pos
>=
64
&&
mb
->
pos
<
127
)
av_log
(
avctx
,
AV_LOG_ERROR
,
"AC EOB marker is absent pos=%d
\n
"
,
mb
->
pos
);
block
+=
64
;
mb
++
;
}
}
/* compute idct and place blocks */
block
=
&
sblock
[
0
][
0
];
mb
=
mb_data
;
for
(
mb_index
=
0
;
mb_index
<
5
;
mb_index
++
)
{
dv_calculate_mb_xy
(
s
,
work_chunk
,
mb_index
,
&
mb_x
,
&
mb_y
);
/* idct_put'ting luminance */
if
((
s
->
sys
->
pix_fmt
==
PIX_FMT_YUV420P
)
||
(
s
->
sys
->
pix_fmt
==
PIX_FMT_YUV411P
&&
mb_x
>=
(
704
/
8
))
||
(
s
->
sys
->
height
>=
720
&&
mb_y
!=
134
))
{
y_stride
=
(
s
->
picture
.
linesize
[
0
]
<<
((
!
is_field_mode
[
mb_index
])
*
log2_blocksize
));
}
else
{
y_stride
=
(
2
<<
log2_blocksize
);
}
y_ptr
=
s
->
picture
.
data
[
0
]
+
((
mb_y
*
s
->
picture
.
linesize
[
0
]
+
mb_x
)
<<
log2_blocksize
);
linesize
=
s
->
picture
.
linesize
[
0
]
<<
is_field_mode
[
mb_index
];
mb
[
0
]
.
idct_put
(
y_ptr
,
linesize
,
block
+
0
*
64
);
if
(
s
->
sys
->
video_stype
==
4
)
{
/* SD 422 */
mb
[
2
].
idct_put
(
y_ptr
+
(
1
<<
log2_blocksize
)
,
linesize
,
block
+
2
*
64
);
}
else
{
mb
[
1
].
idct_put
(
y_ptr
+
(
1
<<
log2_blocksize
)
,
linesize
,
block
+
1
*
64
);
mb
[
2
].
idct_put
(
y_ptr
+
y_stride
,
linesize
,
block
+
2
*
64
);
mb
[
3
].
idct_put
(
y_ptr
+
(
1
<<
log2_blocksize
)
+
y_stride
,
linesize
,
block
+
3
*
64
);
}
mb
+=
4
;
block
+=
4
*
64
;
/* idct_put'ting chrominance */
c_offset
=
(((
mb_y
>>
(
s
->
sys
->
pix_fmt
==
PIX_FMT_YUV420P
))
*
s
->
picture
.
linesize
[
1
]
+
(
mb_x
>>
((
s
->
sys
->
pix_fmt
==
PIX_FMT_YUV411P
)
?
2
:
1
)))
<<
log2_blocksize
);
for
(
j
=
2
;
j
;
j
--
)
{
uint8_t
*
c_ptr
=
s
->
picture
.
data
[
j
]
+
c_offset
;
if
(
s
->
sys
->
pix_fmt
==
PIX_FMT_YUV411P
&&
mb_x
>=
(
704
/
8
))
{
uint64_t
aligned_pixels
[
64
/
8
];
uint8_t
*
pixels
=
(
uint8_t
*
)
aligned_pixels
;
uint8_t
*
c_ptr1
,
*
ptr1
;
int
x
,
y
;
mb
->
idct_put
(
pixels
,
8
,
block
);
for
(
y
=
0
;
y
<
(
1
<<
log2_blocksize
);
y
++
,
c_ptr
+=
s
->
picture
.
linesize
[
j
],
pixels
+=
8
)
{
ptr1
=
pixels
+
(
1
<<
(
log2_blocksize
-
1
));
c_ptr1
=
c_ptr
+
(
s
->
picture
.
linesize
[
j
]
<<
log2_blocksize
);
for
(
x
=
0
;
x
<
(
1
<<
(
log2_blocksize
-
1
));
x
++
)
{
c_ptr
[
x
]
=
pixels
[
x
];
c_ptr1
[
x
]
=
ptr1
[
x
];
}
}
block
+=
64
;
mb
++
;
}
else
{
y_stride
=
(
mb_y
==
134
)
?
(
1
<<
log2_blocksize
)
:
s
->
picture
.
linesize
[
j
]
<<
((
!
is_field_mode
[
mb_index
])
*
log2_blocksize
);
linesize
=
s
->
picture
.
linesize
[
j
]
<<
is_field_mode
[
mb_index
];
(
mb
++
)
->
idct_put
(
c_ptr
,
linesize
,
block
);
block
+=
64
;
if
(
s
->
sys
->
bpm
==
8
)
{
(
mb
++
)
->
idct_put
(
c_ptr
+
y_stride
,
linesize
,
block
);
block
+=
64
;
}
}
}
}
return
0
;
}
/* NOTE: exactly one frame must be given (120000 bytes for NTSC,
144000 bytes for PAL - or twice those for 50Mbps) */
static
int
dvvideo_decode_frame
(
AVCodecContext
*
avctx
,
void
*
data
,
int
*
data_size
,
AVPacket
*
avpkt
)
{
const
uint8_t
*
buf
=
avpkt
->
data
;
int
buf_size
=
avpkt
->
size
;
DVVideoContext
*
s
=
avctx
->
priv_data
;
const
uint8_t
*
vsc_pack
;
int
apt
,
is16_9
;
s
->
sys
=
avpriv_dv_frame_profile
(
s
->
sys
,
buf
,
buf_size
);
if
(
!
s
->
sys
||
buf_size
<
s
->
sys
->
frame_size
||
ff_dv_init_dynamic_tables
(
s
->
sys
))
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"could not find dv frame profile
\n
"
);
return
-
1
;
/* NOTE: we only accept several full frames */
}
if
(
s
->
picture
.
data
[
0
])
avctx
->
release_buffer
(
avctx
,
&
s
->
picture
);
s
->
picture
.
reference
=
0
;
s
->
picture
.
key_frame
=
1
;
s
->
picture
.
pict_type
=
AV_PICTURE_TYPE_I
;
avctx
->
pix_fmt
=
s
->
sys
->
pix_fmt
;
avctx
->
time_base
=
s
->
sys
->
time_base
;
avcodec_set_dimensions
(
avctx
,
s
->
sys
->
width
,
s
->
sys
->
height
);
if
(
avctx
->
get_buffer
(
avctx
,
&
s
->
picture
)
<
0
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"get_buffer() failed
\n
"
);
return
-
1
;
}
s
->
picture
.
interlaced_frame
=
1
;
s
->
picture
.
top_field_first
=
0
;
s
->
buf
=
buf
;
avctx
->
execute
(
avctx
,
dv_decode_video_segment
,
s
->
sys
->
work_chunks
,
NULL
,
dv_work_pool_size
(
s
->
sys
),
sizeof
(
DVwork_chunk
));
emms_c
();
/* return image */
*
data_size
=
sizeof
(
AVFrame
);
*
(
AVFrame
*
)
data
=
s
->
picture
;
/* Determine the codec's sample_aspect ratio from the packet */
vsc_pack
=
buf
+
80
*
5
+
48
+
5
;
if
(
*
vsc_pack
==
dv_video_control
)
{
apt
=
buf
[
4
]
&
0x07
;
is16_9
=
(
vsc_pack
&&
((
vsc_pack
[
2
]
&
0x07
)
==
0x02
||
(
!
apt
&&
(
vsc_pack
[
2
]
&
0x07
)
==
0x07
)));
avctx
->
sample_aspect_ratio
=
s
->
sys
->
sar
[
is16_9
];
}
return
s
->
sys
->
frame_size
;
}
static
int
dvvideo_close
(
AVCodecContext
*
c
)
{
DVVideoContext
*
s
=
c
->
priv_data
;
if
(
s
->
picture
.
data
[
0
])
c
->
release_buffer
(
c
,
&
s
->
picture
);
return
0
;
}
AVCodec
ff_dvvideo_decoder
=
{
.
name
=
"dvvideo"
,
.
type
=
AVMEDIA_TYPE_VIDEO
,
.
id
=
CODEC_ID_DVVIDEO
,
.
priv_data_size
=
sizeof
(
DVVideoContext
),
.
init
=
ff_dvvideo_init
,
.
close
=
dvvideo_close
,
.
decode
=
dvvideo_decode_frame
,
.
capabilities
=
CODEC_CAP_DR1
|
CODEC_CAP_SLICE_THREADS
,
.
max_lowres
=
3
,
.
long_name
=
NULL_IF_CONFIG_SMALL
(
"DV (Digital Video)"
),
};
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment