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
9cfa68c5
Commit
9cfa68c5
authored
Oct 17, 2014
by
Kieran Kunhya
Committed by
Anton Khirnov
Dec 20, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mpegts: add support for Opus
Signed-off-by:
Anton Khirnov
<
anton@khirnov.net
>
parent
8ebf02f8
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
191 additions
and
22 deletions
+191
-22
opus.c
libavcodec/opus.c
+3
-8
opus.h
libavcodec/opus.h
+9
-0
opus_parser.c
libavcodec/opus_parser.c
+126
-13
mpegts.c
libavformat/mpegts.c
+53
-1
No files found.
libavcodec/opus.c
View file @
9cfa68c5
...
...
@@ -290,10 +290,6 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx,
OpusContext
*
s
)
{
static
const
uint8_t
default_channel_map
[
2
]
=
{
0
,
1
};
uint8_t
default_extradata
[
19
]
=
{
'O'
,
'p'
,
'u'
,
's'
,
'H'
,
'e'
,
'a'
,
'd'
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
};
int
(
*
channel_reorder
)(
int
,
int
)
=
channel_reorder_unknown
;
...
...
@@ -308,9 +304,8 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx,
"Multichannel configuration without extradata.
\n
"
);
return
AVERROR
(
EINVAL
);
}
default_extradata
[
9
]
=
(
avctx
->
channels
==
1
)
?
1
:
2
;
extradata
=
default_extradata
;
extradata_size
=
sizeof
(
default_extradata
);
extradata
=
opus_default_extradata
;
extradata_size
=
sizeof
(
opus_default_extradata
);
}
else
{
extradata
=
avctx
->
extradata
;
extradata_size
=
avctx
->
extradata_size
;
...
...
@@ -330,7 +325,7 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx,
avctx
->
delay
=
AV_RL16
(
extradata
+
10
);
channels
=
extradata
[
9
]
;
channels
=
avctx
->
extradata
?
extradata
[
9
]
:
(
avctx
->
channels
==
1
)
?
1
:
2
;
if
(
!
channels
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Zero channel count specified in the extadata
\n
"
);
return
AVERROR_INVALIDDATA
;
...
...
libavcodec/opus.h
View file @
9cfa68c5
...
...
@@ -61,6 +61,15 @@
#define ROUND_MUL16(a,b) ((MUL16(a, b) + 16384) >> 15)
#define opus_ilog(i) (av_log2(i) + !!(i))
#define OPUS_TS_HEADER 0x7FE0 // 0x3ff (11 bits)
#define OPUS_TS_MASK 0xFFE0 // top 11 bits
static
const
uint8_t
opus_default_extradata
[
30
]
=
{
'O'
,
'p'
,
'u'
,
's'
,
'H'
,
'e'
,
'a'
,
'd'
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
};
enum
OpusMode
{
OPUS_MODE_SILK
,
OPUS_MODE_HYBRID
,
...
...
libavcodec/opus_parser.c
View file @
9cfa68c5
...
...
@@ -26,50 +26,163 @@
*/
#include "avcodec.h"
#include "bytestream.h"
#include "opus.h"
#include "parser.h"
typedef
struct
OpusParseContext
{
OpusContext
ctx
;
OpusPacket
pkt
;
int
extradata_parsed
;
ParseContext
pc
;
int
ts_framing
;
}
OpusParseContext
;
static
int
opus_parse
(
AVCodecParserContext
*
ctx
,
AVCodecContext
*
avctx
,
const
uint8_t
**
poutbuf
,
int
*
poutbuf_size
,
const
uint8_t
*
buf
,
int
buf_size
)
static
const
uint8_t
*
parse_opus_ts_header
(
const
uint8_t
*
start
,
int
*
payload_len
,
int
buf_len
)
{
const
uint8_t
*
buf
=
start
+
1
;
int
start_trim_flag
,
end_trim_flag
,
control_extension_flag
,
control_extension_length
,
i
;
uint8_t
flags
;
GetByteContext
gb
;
bytestream2_init
(
&
gb
,
buf
,
buf_len
);
flags
=
bytestream2_get_byte
(
&
gb
);
start_trim_flag
=
(
flags
>>
4
)
&
1
;
end_trim_flag
=
(
flags
>>
3
)
&
1
;
control_extension_flag
=
(
flags
>>
2
)
&
1
;
*
payload_len
=
0
;
while
(
bytestream2_peek_byte
(
&
gb
)
==
0xff
)
*
payload_len
+=
bytestream2_get_byte
(
&
gb
);
*
payload_len
+=
bytestream2_get_byte
(
&
gb
);
if
(
start_trim_flag
)
bytestream2_skip
(
&
gb
,
2
);
if
(
end_trim_flag
)
bytestream2_skip
(
&
gb
,
2
);
if
(
control_extension_flag
)
{
control_extension_length
=
bytestream2_get_byte
(
&
gb
);
bytestream2_skip
(
&
gb
,
control_extension_length
);
}
return
buf
+
bytestream2_tell
(
&
gb
);
}
/**
* Find the end of the current frame in the bitstream.
* @return the position of the first byte of the next frame, or -1
*/
static
int
opus_find_frame_end
(
AVCodecParserContext
*
ctx
,
AVCodecContext
*
avctx
,
const
uint8_t
*
buf
,
int
buf_size
,
int
*
header_len
)
{
OpusParseContext
*
s
=
ctx
->
priv_data
;
int
ret
;
ParseContext
*
pc
=
&
s
->
pc
;
int
ret
,
start_found
,
i
=
0
,
payload_len
=
0
;
const
uint8_t
*
payload
;
uint32_t
state
;
uint16_t
hdr
;
*
header_len
=
0
;
if
(
!
buf_size
)
return
0
;
start_found
=
pc
->
frame_start_found
;
state
=
pc
->
state
;
payload
=
buf
;
/* Check if we're using Opus in MPEG-TS framing */
if
(
!
s
->
ts_framing
&&
buf_size
>
2
)
{
hdr
=
AV_RB16
(
buf
);
if
((
hdr
&
OPUS_TS_MASK
)
==
OPUS_TS_HEADER
)
s
->
ts_framing
=
1
;
}
if
(
s
->
ts_framing
&&
!
start_found
)
{
for
(
i
=
0
;
i
<
buf_size
-
2
;
i
++
)
{
state
=
(
state
<<
8
)
|
payload
[
i
];
if
((
state
&
OPUS_TS_MASK
)
==
OPUS_TS_HEADER
)
{
payload
=
parse_opus_ts_header
(
payload
,
&
payload_len
,
buf_size
-
i
);
*
header_len
=
payload
-
buf
;
start_found
=
1
;
break
;
}
}
}
if
(
!
s
->
ts_framing
)
payload_len
=
buf_size
;
if
(
avctx
->
extradata
&&
!
s
->
extradata_parsed
)
{
ret
=
ff_opus_parse_extradata
(
avctx
,
&
s
->
ctx
);
if
(
ret
<
0
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Error parsing Ogg extradata.
\n
"
);
goto
fail
;
return
AVERROR_INVALIDDATA
;
}
av_freep
(
&
s
->
ctx
.
channel_maps
);
s
->
extradata_parsed
=
1
;
}
ret
=
ff_opus_parse_packet
(
&
s
->
pkt
,
buf
,
buf_size
,
s
->
ctx
.
nb_streams
>
1
);
if
(
ret
<
0
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Error parsing Opus packet header.
\n
"
);
goto
fail
;
if
(
payload_len
<=
buf_size
&&
(
!
s
->
ts_framing
||
start_found
))
{
ret
=
ff_opus_parse_packet
(
&
s
->
pkt
,
payload
,
payload_len
,
s
->
ctx
.
nb_streams
>
1
);
if
(
ret
<
0
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Error parsing Opus packet header.
\n
"
);
pc
->
frame_start_found
=
0
;
return
AVERROR_INVALIDDATA
;
}
ctx
->
duration
=
s
->
pkt
.
frame_count
*
s
->
pkt
.
frame_duration
;
}
ctx
->
duration
=
s
->
pkt
.
frame_count
*
s
->
pkt
.
frame_duration
;
if
(
s
->
ts_framing
)
{
if
(
start_found
)
{
if
(
payload_len
+
*
header_len
<=
buf_size
)
{
pc
->
frame_start_found
=
0
;
pc
->
state
=
-
1
;
return
payload_len
+
*
header_len
;
}
}
pc
->
frame_start_found
=
start_found
;
pc
->
state
=
state
;
return
END_NOT_FOUND
;
}
fail:
*
poutbuf
=
buf
;
*
poutbuf_size
=
buf_size
;
return
buf_size
;
}
static
int
opus_parse
(
AVCodecParserContext
*
ctx
,
AVCodecContext
*
avctx
,
const
uint8_t
**
poutbuf
,
int
*
poutbuf_size
,
const
uint8_t
*
buf
,
int
buf_size
)
{
OpusParseContext
*
s
=
ctx
->
priv_data
;
ParseContext
*
pc
=
&
s
->
pc
;
int
next
,
header_len
;
next
=
opus_find_frame_end
(
ctx
,
avctx
,
buf
,
buf_size
,
&
header_len
);
if
(
s
->
ts_framing
&&
next
!=
AVERROR_INVALIDDATA
&&
ff_combine_frame
(
pc
,
next
,
&
buf
,
&
buf_size
)
<
0
)
{
*
poutbuf
=
NULL
;
*
poutbuf_size
=
0
;
return
buf_size
;
}
if
(
next
==
AVERROR_INVALIDDATA
){
*
poutbuf
=
NULL
;
*
poutbuf_size
=
0
;
return
buf_size
;
}
*
poutbuf
=
buf
+
header_len
;
*
poutbuf_size
=
buf_size
-
header_len
;
return
next
;
}
AVCodecParser
ff_opus_parser
=
{
.
codec_ids
=
{
AV_CODEC_ID_OPUS
},
.
priv_data_size
=
sizeof
(
OpusParseContext
),
.
parser_parse
=
opus_parse
,
.
parser_close
=
ff_parse_close
};
libavformat/mpegts.c
View file @
9cfa68c5
...
...
@@ -28,6 +28,7 @@
#include "libavutil/opt.h"
#include "libavcodec/bytestream.h"
#include "libavcodec/get_bits.h"
#include "libavcodec/opus.h"
#include "avformat.h"
#include "mpegts.h"
#include "internal.h"
...
...
@@ -613,6 +614,7 @@ static const StreamType REGD_types[] = {
{
MKTAG
(
'D'
,
'T'
,
'S'
,
'3'
),
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_DTS
},
{
MKTAG
(
'H'
,
'E'
,
'V'
,
'C'
),
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_HEVC
},
{
MKTAG
(
'V'
,
'C'
,
'-'
,
'1'
),
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_VC1
},
{
MKTAG
(
'O'
,
'p'
,
'u'
,
's'
),
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_OPUS
},
{
0
},
};
...
...
@@ -1314,13 +1316,32 @@ static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section,
av_free
(
mp4_descr
[
i
].
dec_config_descr
);
}
static
const
uint8_t
opus_coupled_stream_cnt
[
9
]
=
{
1
,
0
,
1
,
1
,
2
,
2
,
2
,
3
,
3
};
static
const
uint8_t
opus_stream_cnt
[
9
]
=
{
1
,
1
,
1
,
2
,
2
,
3
,
4
,
4
,
5
,
};
static
const
uint8_t
opus_channel_map
[
8
][
8
]
=
{
{
0
},
{
0
,
1
},
{
0
,
2
,
1
},
{
0
,
1
,
2
,
3
},
{
0
,
4
,
1
,
2
,
3
},
{
0
,
4
,
1
,
2
,
3
,
5
},
{
0
,
4
,
1
,
2
,
3
,
5
,
6
},
{
0
,
6
,
1
,
2
,
3
,
4
,
5
,
7
},
};
int
ff_parse_mpeg2_descriptor
(
AVFormatContext
*
fc
,
AVStream
*
st
,
int
stream_type
,
const
uint8_t
**
pp
,
const
uint8_t
*
desc_list_end
,
Mp4Descr
*
mp4_descr
,
int
mp4_descr_count
,
int
pid
,
MpegTSContext
*
ts
)
{
const
uint8_t
*
desc_end
;
int
desc_len
,
desc_tag
,
desc_es_id
;
int
desc_len
,
desc_tag
,
desc_es_id
,
ext_desc_tag
,
channels
,
channel_config_code
;
char
language
[
252
];
int
i
;
...
...
@@ -1444,6 +1465,37 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
if
(
st
->
codec
->
codec_id
==
AV_CODEC_ID_NONE
)
mpegts_find_stream_type
(
st
,
st
->
codec
->
codec_tag
,
REGD_types
);
break
;
case
0x7f
:
/* DVB extension descriptor */
ext_desc_tag
=
get8
(
pp
,
desc_end
);
if
(
ext_desc_tag
<
0
)
return
AVERROR_INVALIDDATA
;
if
(
st
->
codec
->
codec_id
==
AV_CODEC_ID_OPUS
&&
ext_desc_tag
==
0x80
)
{
/* User defined (provisional Opus) */
if
(
!
st
->
codec
->
extradata
)
{
st
->
codec
->
extradata
=
av_mallocz
(
sizeof
(
opus_default_extradata
)
+
FF_INPUT_BUFFER_PADDING_SIZE
);
if
(
!
st
->
codec
->
extradata
)
return
AVERROR
(
ENOMEM
);
st
->
codec
->
extradata_size
=
sizeof
(
opus_default_extradata
);
memcpy
(
st
->
codec
->
extradata
,
opus_default_extradata
,
sizeof
(
opus_default_extradata
));
channel_config_code
=
get8
(
pp
,
desc_end
);
if
(
channel_config_code
<
0
)
return
AVERROR_INVALIDDATA
;
if
(
channel_config_code
<=
0x8
)
{
st
->
codec
->
extradata
[
9
]
=
channels
=
channel_config_code
?
channel_config_code
:
2
;
st
->
codec
->
extradata
[
18
]
=
channel_config_code
?
(
channels
>
2
)
:
255
;
st
->
codec
->
extradata
[
19
]
=
opus_stream_cnt
[
channel_config_code
];
st
->
codec
->
extradata
[
20
]
=
opus_coupled_stream_cnt
[
channel_config_code
];
memcpy
(
&
st
->
codec
->
extradata
[
21
],
opus_channel_map
[
channels
-
1
],
channels
);
}
else
{
avpriv_request_sample
(
fc
,
"Opus in MPEG-TS - channel_config_code > 0x8"
);
}
st
->
need_parsing
=
AVSTREAM_PARSE_FULL
;
}
}
break
;
default:
break
;
}
...
...
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