Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
bf1a1565
authored
Jan 30, 2022
by
Dustin
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Added support for AVC picOrderCountType = 2
parent
5e7679df
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
48 additions
and
29 deletions
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AvcChunkPeeker.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviExtractor.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviTrack.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/PicCountClock.java
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/PicCountClockTest.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AvcChunkPeeker.java
View file @
bf1a1565
...
@@ -18,6 +18,7 @@ public class AvcChunkPeeker extends NalChunkPeeker {
...
@@ -18,6 +18,7 @@ public class AvcChunkPeeker extends NalChunkPeeker {
private
static
final
int
NAL_TYPE_SEI
=
6
;
private
static
final
int
NAL_TYPE_SEI
=
6
;
private
static
final
int
NAL_TYPE_SPS
=
7
;
private
static
final
int
NAL_TYPE_SPS
=
7
;
private
static
final
int
NAL_TYPE_PPS
=
8
;
private
static
final
int
NAL_TYPE_PPS
=
8
;
private
static
final
int
NAL_TYPE_AUD
=
9
;
private
final
PicCountClock
picCountClock
;
private
final
PicCountClock
picCountClock
;
private
final
Format
.
Builder
formatBuilder
;
private
final
Format
.
Builder
formatBuilder
;
...
@@ -26,15 +27,14 @@ public class AvcChunkPeeker extends NalChunkPeeker {
...
@@ -26,15 +27,14 @@ public class AvcChunkPeeker extends NalChunkPeeker {
private
float
pixelWidthHeightRatio
=
1
f
;
private
float
pixelWidthHeightRatio
=
1
f
;
private
NalUnitUtil
.
SpsData
spsData
;
private
NalUnitUtil
.
SpsData
spsData
;
public
AvcChunkPeeker
(
Format
.
Builder
formatBuilder
,
TrackOutput
trackOutput
,
long
durationUs
,
public
AvcChunkPeeker
(
Format
.
Builder
formatBuilder
,
TrackOutput
trackOutput
,
LinearClock
clock
)
{
int
length
)
{
super
(
16
);
super
(
16
);
this
.
formatBuilder
=
formatBuilder
;
this
.
formatBuilder
=
formatBuilder
;
this
.
trackOutput
=
trackOutput
;
this
.
trackOutput
=
trackOutput
;
picCountClock
=
new
PicCountClock
(
durationUs
,
length
);
picCountClock
=
new
PicCountClock
(
clock
.
durationUs
,
clock
.
length
);
}
}
public
PicCountClock
getPicCoun
tClock
()
{
public
LinearClock
ge
tClock
()
{
return
picCountClock
;
return
picCountClock
;
}
}
...
@@ -58,7 +58,7 @@ public class AvcChunkPeeker extends NalChunkPeeker {
...
@@ -58,7 +58,7 @@ public class AvcChunkPeeker extends NalChunkPeeker {
if
(
spsData
.
separateColorPlaneFlag
)
{
if
(
spsData
.
separateColorPlaneFlag
)
{
in
.
skipBits
(
2
);
//colour_plane_id
in
.
skipBits
(
2
);
//colour_plane_id
}
}
in
.
readBits
(
spsData
.
frameNumLength
);
//frame_num
final
int
frameNum
=
in
.
readBits
(
spsData
.
frameNumLength
);
//frame_num
if
(!
spsData
.
frameMbsOnlyFlag
)
{
if
(!
spsData
.
frameMbsOnlyFlag
)
{
boolean
field_pic_flag
=
in
.
readBit
();
// field_pic_flag
boolean
field_pic_flag
=
in
.
readBit
();
// field_pic_flag
if
(
field_pic_flag
)
{
if
(
field_pic_flag
)
{
...
@@ -71,6 +71,9 @@ public class AvcChunkPeeker extends NalChunkPeeker {
...
@@ -71,6 +71,9 @@ public class AvcChunkPeeker extends NalChunkPeeker {
//Log.d("Test", "FrameNum: " + frame + " cnt=" + picOrderCountLsb);
//Log.d("Test", "FrameNum: " + frame + " cnt=" + picOrderCountLsb);
picCountClock
.
setPicCount
(
picOrderCountLsb
);
picCountClock
.
setPicCount
(
picOrderCountLsb
);
return
;
return
;
}
else
if
(
spsData
.
picOrderCountType
==
2
)
{
picCountClock
.
setPicCount
(
frameNum
);
return
;
}
}
picCountClock
.
setIndex
(
picCountClock
.
getIndex
());
picCountClock
.
setIndex
(
picCountClock
.
getIndex
());
}
}
...
@@ -80,7 +83,12 @@ public class AvcChunkPeeker extends NalChunkPeeker {
...
@@ -80,7 +83,12 @@ public class AvcChunkPeeker extends NalChunkPeeker {
final
int
spsStart
=
nalTypeOffset
+
1
;
final
int
spsStart
=
nalTypeOffset
+
1
;
nalTypeOffset
=
seekNextNal
(
input
,
spsStart
);
nalTypeOffset
=
seekNextNal
(
input
,
spsStart
);
spsData
=
NalUnitUtil
.
parseSpsNalUnitPayload
(
buffer
,
spsStart
,
pos
);
spsData
=
NalUnitUtil
.
parseSpsNalUnitPayload
(
buffer
,
spsStart
,
pos
);
picCountClock
.
setMaxPicCount
(
1
<<
(
spsData
.
picOrderCntLsbLength
));
if
(
spsData
.
picOrderCountType
==
0
)
{
picCountClock
.
setMaxPicCount
(
1
<<
spsData
.
picOrderCntLsbLength
,
2
);
}
else
if
(
spsData
.
picOrderCountType
==
2
)
{
//Plus one because we double the frame number
picCountClock
.
setMaxPicCount
(
1
<<
spsData
.
frameNumLength
,
1
);
}
if
(
spsData
.
pixelWidthHeightRatio
!=
pixelWidthHeightRatio
)
{
if
(
spsData
.
pixelWidthHeightRatio
!=
pixelWidthHeightRatio
)
{
pixelWidthHeightRatio
=
spsData
.
pixelWidthHeightRatio
;
pixelWidthHeightRatio
=
spsData
.
pixelWidthHeightRatio
;
formatBuilder
.
setPixelWidthHeightRatio
(
pixelWidthHeightRatio
);
formatBuilder
.
setPixelWidthHeightRatio
(
pixelWidthHeightRatio
);
...
@@ -103,6 +111,7 @@ public class AvcChunkPeeker extends NalChunkPeeker {
...
@@ -103,6 +111,7 @@ public class AvcChunkPeeker extends NalChunkPeeker {
case
NAL_TYPE_IRD:
case
NAL_TYPE_IRD:
picCountClock
.
syncIndexes
();
picCountClock
.
syncIndexes
();
return
;
return
;
case
NAL_TYPE_AUD:
case
NAL_TYPE_SEI:
case
NAL_TYPE_SEI:
case
NAL_TYPE_PPS:
{
case
NAL_TYPE_PPS:
{
nalTypeOffset
=
seekNextNal
(
input
,
nalTypeOffset
);
nalTypeOffset
=
seekNextNal
(
input
,
nalTypeOffset
);
...
...
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviExtractor.java
View file @
bf1a1565
...
@@ -255,15 +255,14 @@ public class AviExtractor implements Extractor {
...
@@ -255,15 +255,14 @@ public class AviExtractor implements Extractor {
builder
.
setFrameRate
(
streamHeader
.
getFrameRate
());
builder
.
setFrameRate
(
streamHeader
.
getFrameRate
());
builder
.
setSampleMimeType
(
mimeType
);
builder
.
setSampleMimeType
(
mimeType
);
final
LinearClock
clock
=
new
LinearClock
(
durationUs
,
length
);
aviTrack
=
new
AviTrack
(
streamId
,
C
.
TRACK_TYPE_VIDEO
,
clock
,
trackOutput
);
if
(
MimeTypes
.
VIDEO_H264
.
equals
(
mimeType
))
{
if
(
MimeTypes
.
VIDEO_H264
.
equals
(
mimeType
))
{
final
AvcChunkPeeker
avcChunkPeeker
=
new
AvcChunkPeeker
(
builder
,
trackOutput
,
durationUs
,
final
AvcChunkPeeker
avcChunkPeeker
=
new
AvcChunkPeeker
(
builder
,
trackOutput
,
clock
);
length
);
aviTrack
.
setClock
(
avcChunkPeeker
.
getClock
());
aviTrack
=
new
AviTrack
(
streamId
,
C
.
TRACK_TYPE_VIDEO
,
avcChunkPeeker
.
getPicCountClock
(),
trackOutput
);
aviTrack
.
setChunkPeeker
(
avcChunkPeeker
);
aviTrack
.
setChunkPeeker
(
avcChunkPeeker
);
}
else
{
}
else
{
aviTrack
=
new
AviTrack
(
streamId
,
C
.
TRACK_TYPE_VIDEO
,
new
LinearClock
(
durationUs
,
length
),
trackOutput
);
if
(
MimeTypes
.
VIDEO_MP4V
.
equals
(
mimeType
))
{
if
(
MimeTypes
.
VIDEO_MP4V
.
equals
(
mimeType
))
{
aviTrack
.
setChunkPeeker
(
new
Mp4vChunkPeeker
(
builder
,
trackOutput
));
aviTrack
.
setChunkPeeker
(
new
Mp4vChunkPeeker
(
builder
,
trackOutput
));
}
}
...
@@ -361,9 +360,10 @@ public class AviExtractor implements Extractor {
...
@@ -361,9 +360,10 @@ public class AviExtractor implements Extractor {
return
null
;
return
null
;
}
}
void
updateAudioTiming
(
final
int
[]
keyFrameCounts
,
final
long
videoDuration
)
{
void
fixTimings
(
final
int
[]
keyFrameCounts
,
final
long
videoDuration
)
{
for
(
final
AviTrack
aviTrack
:
aviTracks
)
{
for
(
final
AviTrack
aviTrack
:
aviTracks
)
{
if
(
aviTrack
!=
null
&&
aviTrack
.
isAudio
())
{
if
(
aviTrack
!=
null
)
{
if
(
aviTrack
.
isAudio
())
{
final
long
durationUs
=
aviTrack
.
getClock
().
durationUs
;
final
long
durationUs
=
aviTrack
.
getClock
().
durationUs
;
i
(
"Audio #"
+
aviTrack
.
id
+
" chunks: "
+
aviTrack
.
chunks
+
" us="
+
durationUs
+
i
(
"Audio #"
+
aviTrack
.
id
+
" chunks: "
+
aviTrack
.
chunks
+
" us="
+
durationUs
+
" size="
+
aviTrack
.
size
);
" size="
+
aviTrack
.
size
);
...
@@ -378,6 +378,13 @@ public class AviExtractor implements Extractor {
...
@@ -378,6 +378,13 @@ public class AviExtractor implements Extractor {
w
(
"Audio is not all key frames chunks="
+
aviTrack
.
chunks
+
" keyFrames="
+
w
(
"Audio is not all key frames chunks="
+
aviTrack
.
chunks
+
" keyFrames="
+
keyFrameCounts
[
aviTrack
.
id
]);
keyFrameCounts
[
aviTrack
.
id
]);
}
}
}
/* else if (aviTrack.isVideo()) {
final LinearClock clock = aviTrack.getClock();
if (clock.length != aviTrack.chunks) {
w("Video #" + aviTrack.id + " chunks != length changing FPS");
clock.setLength(aviTrack.chunks);
}
}*/
}
}
}
}
}
}
...
@@ -464,8 +471,7 @@ public class AviExtractor implements Extractor {
...
@@ -464,8 +471,7 @@ public class AviExtractor implements Extractor {
i
(
"Video chunks="
+
videoTrack
.
chunks
+
" us="
+
seekMap
.
getDurationUs
());
i
(
"Video chunks="
+
videoTrack
.
chunks
+
" us="
+
seekMap
.
getDurationUs
());
//Needs to be called after the duration is updated
fixTimings
(
keyFrameCounts
,
durationUs
);
updateAudioTiming
(
keyFrameCounts
,
durationUs
);
setSeekMap
(
seekMap
);
setSeekMap
(
seekMap
);
}
}
...
...
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/AviTrack.java
View file @
bf1a1565
...
@@ -20,7 +20,7 @@ public class AviTrack {
...
@@ -20,7 +20,7 @@ public class AviTrack {
final
@C
.
TrackType
int
trackType
;
final
@C
.
TrackType
int
trackType
;
@NonNull
@NonNull
final
LinearClock
clock
;
LinearClock
clock
;
@NonNull
@NonNull
final
TrackOutput
trackOutput
;
final
TrackOutput
trackOutput
;
...
@@ -56,7 +56,7 @@ public class AviTrack {
...
@@ -56,7 +56,7 @@ public class AviTrack {
return
getChunkIdLower
(
id
)
|
(
'w'
<<
16
)
|
(
'b'
<<
24
);
return
getChunkIdLower
(
id
)
|
(
'w'
<<
16
)
|
(
'b'
<<
24
);
}
}
AviTrack
(
int
id
,
final
@C
.
TrackType
int
trackType
,
@NonNull
LinearClock
clock
,
AviTrack
(
int
id
,
@C
.
TrackType
int
trackType
,
@NonNull
LinearClock
clock
,
@NonNull
TrackOutput
trackOutput
)
{
@NonNull
TrackOutput
trackOutput
)
{
this
.
id
=
id
;
this
.
id
=
id
;
this
.
clock
=
clock
;
this
.
clock
=
clock
;
...
@@ -77,10 +77,15 @@ public class AviTrack {
...
@@ -77,10 +77,15 @@ public class AviTrack {
return
this
.
chunkId
==
chunkId
||
chunkIdAlt
==
chunkId
;
return
this
.
chunkId
==
chunkId
||
chunkIdAlt
==
chunkId
;
}
}
@NonNull
public
LinearClock
getClock
()
{
public
LinearClock
getClock
()
{
return
clock
;
return
clock
;
}
}
public
void
setClock
(
@NonNull
LinearClock
clock
)
{
this
.
clock
=
clock
;
}
public
void
setChunkPeeker
(
ChunkPeeker
chunkPeeker
)
{
public
void
setChunkPeeker
(
ChunkPeeker
chunkPeeker
)
{
this
.
chunkPeeker
=
chunkPeeker
;
this
.
chunkPeeker
=
chunkPeeker
;
}
}
...
@@ -144,7 +149,7 @@ public class AviTrack {
...
@@ -144,7 +149,7 @@ public class AviTrack {
trackOutput
.
sampleMetadata
(
trackOutput
.
sampleMetadata
(
clock
.
getUs
(),
(
isKeyFrame
()
?
C
.
BUFFER_FLAG_KEY_FRAME
:
0
),
size
,
0
,
null
);
clock
.
getUs
(),
(
isKeyFrame
()
?
C
.
BUFFER_FLAG_KEY_FRAME
:
0
),
size
,
0
,
null
);
final
LinearClock
clock
=
getClock
();
final
LinearClock
clock
=
getClock
();
//
Log.d(AviExtractor.TAG, "Frame: " + (isVideo()? 'V' : 'A') + " us=" + clock.getUs() + " size=" + size + " frame=" + clock.getIndex() + " key=" + isKeyFrame());
Log
.
d
(
AviExtractor
.
TAG
,
"Frame: "
+
(
isVideo
()?
'V'
:
'A'
)
+
" us="
+
clock
.
getUs
()
+
" size="
+
size
+
" frame="
+
clock
.
getIndex
()
+
" key="
+
isKeyFrame
());
clock
.
advance
();
clock
.
advance
();
}
}
}
}
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/avi/PicCountClock.java
View file @
bf1a1565
...
@@ -4,14 +4,13 @@ package com.google.android.exoplayer2.extractor.avi;
...
@@ -4,14 +4,13 @@ package com.google.android.exoplayer2.extractor.avi;
* Properly calculates the frame time for H264 frames using PicCount
* Properly calculates the frame time for H264 frames using PicCount
*/
*/
public
class
PicCountClock
extends
LinearClock
{
public
class
PicCountClock
extends
LinearClock
{
//I believe this is 2 because there is a bottom pic order and a top pic order
private
static
final
int
STEP
=
2
;
//The frame as a calculated from the picCount
//The frame as a calculated from the picCount
private
int
picIndex
;
private
int
picIndex
;
private
int
lastPicCount
;
private
int
lastPicCount
;
//Largest picFrame, used when we hit an I frame
//Largest picFrame, used when we hit an I frame
private
int
maxPicIndex
=-
1
;
private
int
maxPicIndex
=-
1
;
private
int
maxPicCount
;
private
int
maxPicCount
;
private
int
step
=
2
;
private
int
posHalf
;
private
int
posHalf
;
private
int
negHalf
;
private
int
negHalf
;
...
@@ -19,15 +18,15 @@ public class PicCountClock extends LinearClock {
...
@@ -19,15 +18,15 @@ public class PicCountClock extends LinearClock {
super
(
durationUs
,
length
);
super
(
durationUs
,
length
);
}
}
public
void
setMaxPicCount
(
int
maxPicCount
)
{
public
void
setMaxPicCount
(
int
maxPicCount
,
int
step
)
{
this
.
maxPicCount
=
maxPicCount
;
this
.
maxPicCount
=
maxPicCount
;
posHalf
=
maxPicCount
/
STEP
;
this
.
step
=
step
;
posHalf
=
maxPicCount
/
step
;
negHalf
=
-
posHalf
;
negHalf
=
-
posHalf
;
}
}
/**
/**
* Done on seek. May cause sync issues if frame picCount != 0 (I frames are always 0)
* Used primarily on seek. May cause issues if not a key frame
* @param index
*/
*/
@Override
@Override
public
void
setIndex
(
int
index
)
{
public
void
setIndex
(
int
index
)
{
...
@@ -42,7 +41,7 @@ public class PicCountClock extends LinearClock {
...
@@ -42,7 +41,7 @@ public class PicCountClock extends LinearClock {
}
else
if
(
delta
>
posHalf
)
{
}
else
if
(
delta
>
posHalf
)
{
delta
-=
maxPicCount
;
delta
-=
maxPicCount
;
}
}
picIndex
+=
delta
/
STEP
;
picIndex
+=
delta
/
step
;
lastPicCount
=
picCount
;
lastPicCount
=
picCount
;
if
(
maxPicIndex
<
picIndex
)
{
if
(
maxPicIndex
<
picIndex
)
{
maxPicIndex
=
picIndex
;
maxPicIndex
=
picIndex
;
...
...
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/avi/PicCountClockTest.java
View file @
bf1a1565
...
@@ -7,7 +7,7 @@ public class PicCountClockTest {
...
@@ -7,7 +7,7 @@ public class PicCountClockTest {
@Test
@Test
public
void
us_givenTwoStepsForward
()
{
public
void
us_givenTwoStepsForward
()
{
final
PicCountClock
picCountClock
=
new
PicCountClock
(
10_000L
,
100
);
final
PicCountClock
picCountClock
=
new
PicCountClock
(
10_000L
,
100
);
picCountClock
.
setMaxPicCount
(
16
*
2
);
picCountClock
.
setMaxPicCount
(
16
*
2
,
2
);
picCountClock
.
setPicCount
(
2
*
2
);
picCountClock
.
setPicCount
(
2
*
2
);
Assert
.
assertEquals
(
2
*
100
,
picCountClock
.
getUs
());
Assert
.
assertEquals
(
2
*
100
,
picCountClock
.
getUs
());
}
}
...
@@ -15,7 +15,7 @@ public class PicCountClockTest {
...
@@ -15,7 +15,7 @@ public class PicCountClockTest {
@Test
@Test
public
void
us_givenThreeStepsBackwards
()
{
public
void
us_givenThreeStepsBackwards
()
{
final
PicCountClock
picCountClock
=
new
PicCountClock
(
10_000L
,
100
);
final
PicCountClock
picCountClock
=
new
PicCountClock
(
10_000L
,
100
);
picCountClock
.
setMaxPicCount
(
16
*
2
);
picCountClock
.
setMaxPicCount
(
16
*
2
,
2
);
picCountClock
.
setPicCount
(
4
*
2
);
// 400ms
picCountClock
.
setPicCount
(
4
*
2
);
// 400ms
Assert
.
assertEquals
(
400
,
picCountClock
.
getUs
());
Assert
.
assertEquals
(
400
,
picCountClock
.
getUs
());
picCountClock
.
setPicCount
(
1
*
2
);
picCountClock
.
setPicCount
(
1
*
2
);
...
@@ -32,7 +32,7 @@ public class PicCountClockTest {
...
@@ -32,7 +32,7 @@ public class PicCountClockTest {
@Test
@Test
public
void
us_giveWrapBackwards
()
{
public
void
us_giveWrapBackwards
()
{
final
PicCountClock
picCountClock
=
new
PicCountClock
(
10_000L
,
100
);
final
PicCountClock
picCountClock
=
new
PicCountClock
(
10_000L
,
100
);
picCountClock
.
setMaxPicCount
(
16
*
2
);
picCountClock
.
setMaxPicCount
(
16
*
2
,
2
);
//Need to walk up no faster than maxPicCount / 2
//Need to walk up no faster than maxPicCount / 2
picCountClock
.
setPicCount
(
7
*
2
);
picCountClock
.
setPicCount
(
7
*
2
);
picCountClock
.
setPicCount
(
11
*
2
);
picCountClock
.
setPicCount
(
11
*
2
);
...
...
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