Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
F
ffmpeg
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
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
ffmpeg
Commits
76a8c3b5
Commit
76a8c3b5
authored
Oct 12, 2018
by
Josh de Kock
Committed by
Kieran Kunhya
Oct 23, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
h264/pic_timing: support multiple timecodes
parent
4241e44a
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
65 additions
and
43 deletions
+65
-43
h264_sei.c
libavcodec/h264_sei.c
+12
-9
h264_sei.h
libavcodec/h264_sei.h
+20
-8
h264_slice.c
libavcodec/h264_slice.c
+33
-26
No files found.
libavcodec/h264_sei.c
View file @
76a8c3b5
...
...
@@ -84,8 +84,10 @@ static int decode_picture_timing(H264SEIPictureTiming *h, GetBitContext *gb,
return
AVERROR_INVALIDDATA
;
num_clock_ts
=
sei_num_clock_ts_table
[
h
->
pic_struct
];
h
->
timecode_cnt
=
0
;
for
(
i
=
0
;
i
<
num_clock_ts
;
i
++
)
{
if
(
get_bits
(
gb
,
1
))
{
/* clock_timestamp_flag */
H264SEITimeCode
*
tc
=
&
h
->
timecode
[
h
->
timecode_cnt
++
];
unsigned
int
full_timestamp_flag
;
unsigned
int
counting_type
,
cnt_dropped_flag
;
h
->
ct_type
|=
1
<<
get_bits
(
gb
,
2
);
...
...
@@ -95,20 +97,21 @@ static int decode_picture_timing(H264SEIPictureTiming *h, GetBitContext *gb,
skip_bits
(
gb
,
1
);
/* discontinuity_flag */
cnt_dropped_flag
=
get_bits
(
gb
,
1
);
/* cnt_dropped_flag */
if
(
cnt_dropped_flag
&&
counting_type
>
1
&&
counting_type
<
7
)
h
->
tc_
dropframe
=
1
;
h
->
tc_frames
=
get_bits
(
gb
,
8
);
/* n_frames */
tc
->
dropframe
=
1
;
tc
->
frame
=
get_bits
(
gb
,
8
);
/* n_frames */
if
(
full_timestamp_flag
)
{
h
->
fulltc_received
=
1
;
h
->
tc_
seconds
=
get_bits
(
gb
,
6
);
/* seconds_value 0..59 */
h
->
tc_
minutes
=
get_bits
(
gb
,
6
);
/* minutes_value 0..59 */
h
->
tc_
hours
=
get_bits
(
gb
,
5
);
/* hours_value 0..23 */
tc
->
full
=
1
;
tc
->
seconds
=
get_bits
(
gb
,
6
);
/* seconds_value 0..59 */
tc
->
minutes
=
get_bits
(
gb
,
6
);
/* minutes_value 0..59 */
tc
->
hours
=
get_bits
(
gb
,
5
);
/* hours_value 0..23 */
}
else
{
tc
->
seconds
=
tc
->
minutes
=
tc
->
hours
=
tc
->
full
=
0
;
if
(
get_bits
(
gb
,
1
))
{
/* seconds_flag */
h
->
tc_
seconds
=
get_bits
(
gb
,
6
);
tc
->
seconds
=
get_bits
(
gb
,
6
);
if
(
get_bits
(
gb
,
1
))
{
/* minutes_flag */
h
->
tc_
minutes
=
get_bits
(
gb
,
6
);
tc
->
minutes
=
get_bits
(
gb
,
6
);
if
(
get_bits
(
gb
,
1
))
/* hours_flag */
h
->
tc_minute
s
=
get_bits
(
gb
,
5
);
tc
->
hour
s
=
get_bits
(
gb
,
5
);
}
}
}
...
...
libavcodec/h264_sei.h
View file @
76a8c3b5
...
...
@@ -67,6 +67,17 @@ typedef enum {
H264_SEI_FPA_TYPE_2D
=
6
,
}
H264_SEI_FpaType
;
typedef
struct
H264SEITimeCode
{
/* When not continuously receiving full timecodes, we have to reference
the previous timecode received */
int
full
;
int
frame
;
int
seconds
;
int
minutes
;
int
hours
;
int
dropframe
;
}
H264SEITimeCode
;
typedef
struct
H264SEIPictureTiming
{
int
present
;
H264_SEI_PicStructType
pic_struct
;
...
...
@@ -88,14 +99,15 @@ typedef struct H264SEIPictureTiming {
*/
int
cpb_removal_delay
;
/* When not continuously receiving full timecodes, we have to reference
the previous timecode received */
int
fulltc_received
;
int
tc_frames
;
int
tc_seconds
;
int
tc_minutes
;
int
tc_hours
;
int
tc_dropframe
;
/**
* Maximum three timecodes in a pic_timing SEI.
*/
H264SEITimeCode
timecode
[
3
];
/**
* Number of timecode in use
*/
int
timecode_cnt
;
}
H264SEIPictureTiming
;
typedef
struct
H264SEIAFD
{
...
...
libavcodec/h264_slice.c
View file @
76a8c3b5
...
...
@@ -1287,42 +1287,49 @@ static int h264_export_frame_props(H264Context *h)
h
->
avctx
->
properties
|=
FF_CODEC_PROPERTY_CLOSED_CAPTIONS
;
}
if
(
h
->
sei
.
picture_timing
.
fulltc_received
)
{
if
(
h
->
sei
.
picture_timing
.
timecode_cnt
>
0
)
{
uint32_t
tc
=
0
;
uint32_t
frames
;
uint32_t
*
tc_sd
;
AVFrameSideData
*
tcside
=
av_frame_new_side_data
(
cur
->
f
,
AV_FRAME_DATA_S12M_TIMECODE
,
sizeof
(
uint32_t
));
sizeof
(
uint32_t
)
*
4
);
if
(
!
tcside
)
return
AVERROR
(
ENOMEM
);
/* For SMPTE 12-M timecodes, frame count is a special case if > 30 FPS.
See SMPTE ST 12-1:2014 Sec 12.1 for more info. */
if
(
av_cmp_q
(
h
->
avctx
->
framerate
,
(
AVRational
)
{
30
,
1
})
==
1
)
{
frames
=
h
->
sei
.
picture_timing
.
tc_frames
/
2
;
if
(
h
->
sei
.
picture_timing
.
tc_frames
%
2
==
1
)
{
if
(
av_cmp_q
(
h
->
avctx
->
framerate
,
(
AVRational
)
{
50
,
1
})
==
0
)
tc
|=
(
1
<<
7
);
else
tc
|=
(
1
<<
23
);
tc_sd
=
(
uint32_t
*
)
tcside
->
data
;
tc_sd
[
0
]
=
h
->
sei
.
picture_timing
.
timecode_cnt
;
for
(
int
i
=
0
;
i
<
tc_sd
[
0
];
i
++
)
{
uint32_t
frames
;
/* For SMPTE 12-M timecodes, frame count is a special case if > 30 FPS.
See SMPTE ST 12-1:2014 Sec 12.1 for more info. */
if
(
av_cmp_q
(
h
->
avctx
->
framerate
,
(
AVRational
)
{
30
,
1
})
==
1
)
{
frames
=
h
->
sei
.
picture_timing
.
timecode
[
i
].
frame
/
2
;
if
(
h
->
sei
.
picture_timing
.
timecode
[
i
].
frame
%
2
==
1
)
{
if
(
av_cmp_q
(
h
->
avctx
->
framerate
,
(
AVRational
)
{
50
,
1
})
==
0
)
tc
|=
(
1
<<
7
);
else
tc
|=
(
1
<<
23
);
}
}
else
{
frames
=
h
->
sei
.
picture_timing
.
timecode
[
i
].
frame
;
}
}
else
{
frames
=
h
->
sei
.
picture_timing
.
tc_frames
;
}
tc
|=
h
->
sei
.
picture_timing
.
tc_
dropframe
<<
30
;
tc
|=
(
frames
/
10
)
<<
28
;
tc
|=
(
frames
%
10
)
<<
24
;
tc
|=
(
h
->
sei
.
picture_timing
.
tc_
seconds
/
10
)
<<
20
;
tc
|=
(
h
->
sei
.
picture_timing
.
tc_
seconds
%
10
)
<<
16
;
tc
|=
(
h
->
sei
.
picture_timing
.
tc_
minutes
/
10
)
<<
12
;
tc
|=
(
h
->
sei
.
picture_timing
.
tc_
minutes
%
10
)
<<
8
;
tc
|=
(
h
->
sei
.
picture_timing
.
tc_
hours
/
10
)
<<
4
;
tc
|=
(
h
->
sei
.
picture_timing
.
tc_
hours
%
10
);
tc
|=
h
->
sei
.
picture_timing
.
timecode
[
i
].
dropframe
<<
30
;
tc
|=
(
frames
/
10
)
<<
28
;
tc
|=
(
frames
%
10
)
<<
24
;
tc
|=
(
h
->
sei
.
picture_timing
.
timecode
[
i
].
seconds
/
10
)
<<
20
;
tc
|=
(
h
->
sei
.
picture_timing
.
timecode
[
i
].
seconds
%
10
)
<<
16
;
tc
|=
(
h
->
sei
.
picture_timing
.
timecode
[
i
].
minutes
/
10
)
<<
12
;
tc
|=
(
h
->
sei
.
picture_timing
.
timecode
[
i
].
minutes
%
10
)
<<
8
;
tc
|=
(
h
->
sei
.
picture_timing
.
timecode
[
i
].
hours
/
10
)
<<
4
;
tc
|=
(
h
->
sei
.
picture_timing
.
timecode
[
i
].
hours
%
10
);
memcpy
(
tcside
->
data
,
&
tc
,
sizeof
(
uint32_t
));
h
->
sei
.
picture_timing
.
fulltc_received
=
0
;
tc_sd
[
i
+
1
]
=
tc
;
}
h
->
sei
.
picture_timing
.
timecode_cnt
=
0
;
}
if
(
h
->
sei
.
alternative_transfer
.
present
&&
...
...
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