Browse Source

增加可以反复重置解码头

worker
langhuihui 6 years ago
parent
commit
5b743786be
  1. 25
      Jessibuca.cpp
  2. 216
      MemoryStream.h
  3. 100
      VideoDecoder.h
  4. 46
      ffmpeg.h
  5. 6
      libde265.h
  6. 9
      libhevc.h
  7. 38
      public/ff_aac.js

25
Jessibuca.cpp

@ -213,38 +213,19 @@ struct Jessica
}
void decodeVideo(clock_t _timestamp, IOBuffer data)
{
u8 avc_packet_type = data[1]; //0为AVCSequence Header,1为AVC NALU,2为AVC end ofsequence
if (waitFirstVideo)
{
u8 frame_type = data[0];
int codec_id = frame_type & 0x0f;
frame_type = (frame_type >> 4) & 0x0f;
if (codec_id == 7)
if (videoDecoder.isAVCSequence(data))
{
emscripten_log(0, "got h264 video");
}
else if (codec_id == 12)
{
emscripten_log(0, "got h265 video");
}
else
{
emscripten_log(0, "Only support video h.264/avc or h.265/hevc codec. actual=%d", codec_id);
return;
}
if (frame_type == 1 && avc_packet_type == 0)
{
videoDecoder.decodeHeader(data, codec_id);
videoDecoder.decode(data);
waitFirstVideo = false;
emscripten_log(0, "video info set!");
}
}
else if (avc_packet_type == 1)
else if (data[1] == 1 || data[1] == 0)
{
if (_timestamp == 0)
return;
data >>= 5;
if (videoBuffer && (bufferIsPlaying || checkTimeout(_timestamp)))
{
videoBuffers.emplace(_timestamp, data);

216
MemoryStream.h

@ -1,216 +0,0 @@
#pragma once
template <int N>
inline void reverse(u8 *a, u8 *b)
{
*a = *b;
reverse<N - 1>(a + 1, b - 1);
}
template <>
inline void reverse<1>(u8 *a, u8 *b)
{
*a = *b;
}
class MemoryStream
{
public:
string data;
int offset;
MemoryStream() : offset(0), data()
{
}
MemoryStream(u8 *bytes, size_t size) : offset(0), data()
{
data.resize(size);
memcpy((void *)point(), bytes, size);
}
MemoryStream(const MemoryStream &right) : data(), offset(right.offset)
{
data.append(right.data);
}
MemoryStream &operator=(const MemoryStream &right)
{
if (this != &right)
{
data = right.data;
offset = right.offset;
}
return *this;
}
MemoryStream(MemoryStream &&right) : data(move(right.data)), offset(right.offset)
{
}
MemoryStream &operator=(MemoryStream &&right)
{
if (this != &right)
{
data = move(right.data);
offset = right.offset;
}
return *this;
}
MemoryStream(string &&right) : data(forward<string>(right)), offset(0)
{
}
MemoryStream(string &right) : data(move(right)), offset(0)
{
}
MemoryStream &operator=(string &&right)
{
data = move(right);
offset = 0;
return *this;
}
MemoryStream operator+(MemoryStream &&right)
{
return MemoryStream(data + right.data);
}
MemoryStream &operator>>=(const int &i)
{
offset += i;
return *this;
}
MemoryStream &operator<<=(const int &i)
{
offset -= i;
return *this;
}
MemoryStream &operator<<(const string &i)
{
data.append(i);
return *this;
}
MemoryStream &operator<<(const MemoryStream &i)
{
data.append(i.data);
return *this;
}
operator const char *()
{
return data.data() + offset;
}
operator const u8 *()
{
return (const u8 *)data.data() + offset;
}
u8 &operator[](int i)
{
u8 *u8s = (u8 *)data.data() + offset;
return u8s[i];
}
template <int N, class T>
MemoryStream &readB(T &out)
{
reverse<N>((u8 *)&out, (u8 *)data.data() + offset + N - 1);
offset += N;
return *this;
}
template <int N, class T>
T readB()
{
T out;
reverse<N>((u8 *)&out, (u8 *)data.data() + offset + N - 1);
offset += N;
return out;
}
#define readu8 readB<1, u8>
#define readUInt16B readB<2, unsigned short>
#define readUInt24B readB<3, unsigned int>
#define readUInt32B readB<4, unsigned int>
#define readDoubleB readB<8, double>
#define read1 readB<1>
#define read2B readB<2>
#define read3B readB<3>
#define read4B readB<4>
#define read8B readB<8>
template <class T>
MemoryStream &readNormal(T &out)
{
out = *(T *)(data.data() + offset);
offset += sizeof(T);
return *this;
}
template <class T>
T readNormal()
{
T out;
out = *(T *)(data.data() + offset);
offset += sizeof(T);
return out;
}
MemoryStream &operator()(int newPos)
{
offset = newPos >= 0 ? newPos : size() + newPos + 1;
return *this;
}
MemoryStream &readFrom(MemoryStream &source, size_t size)
{
checkAvbSize(size);
memcpy((void *)point(), source.point(), size);
source.offset += size;
offset += size;
return *this;
}
const char *point()
{
return data.data() + offset;
}
void checkAvbSize(size_t s)
{
if (offset + s > data.size())
{
data.resize(offset + s);
}
}
string readString(size_t len = string::npos)
{
string result = data.substr(offset, len);
offset += result.length();
return result;
}
void clear()
{
data.resize(0);
offset = 0;
}
void removeConsume()
{
auto l = length();
memmove((void *)data.data(), point(), l);
data.resize(l);
offset = 0;
}
int size() const
{
return data.length();
}
int length() const
{
return data.length() - offset;
}
~MemoryStream()
{
}
void consoleHex(int size)
{
if(size == 0) size = data.length();
string output(3 * size + 1, '\0');
char *hex_buf = (char *)output.c_str();
bool hasOffset = false;
for (int i = 0; i < size; ++i)
{
unsigned char c = data[i];
unsigned int nIntVal = c;
if (!hasOffset)
{
if (offset == i)
{
hasOffset = true;
hex_buf[i * 3] = '#';
}
}
sprintf(hex_buf + i * 3 + (hasOffset ? 1 : 0), "%02x,", nIntVal);
}
val::global("console").call<void>("log", output);
}
};

100
VideoDecoder.h

@ -13,7 +13,7 @@ struct VideoPacket
};
class VideoDecoder
{
public:
public:
val *jsObject;
u8 *heap;
u32 videoWidth;
@ -70,50 +70,76 @@ class VideoDecoder
jsObject->call<void>("draw");
}
virtual void decodeHeader(IOBuffer &data, int codec_id)
virtual void decodeH264Header(IOBuffer &data)
{
emscripten_log(0, "codec = %d", codec_id);
if (codec_id == 7)
u8 lengthSizeMinusOne = data[4];
lengthSizeMinusOne &= 0x03;
NAL_unit_length = lengthSizeMinusOne;
data >>= 6;
//data.consoleHex();
int spsLen = 0;
int ppsLen = 0;
data.read2B(spsLen);
if (spsLen > 0)
{
u8 lengthSizeMinusOne = data[9];
lengthSizeMinusOne &= 0x03;
NAL_unit_length = lengthSizeMinusOne;
data>>=11;
//data.consoleHex();
int spsLen = 0;
int ppsLen = 0;
data.read2B(spsLen);
if (spsLen > 0)
{
_decode(data(0,spsLen));
data >>= spsLen;
}
data >>= 1;
data.read2B(ppsLen);
if (ppsLen > 0)
_decode(data(0, spsLen));
data >>= spsLen;
}
data >>= 1;
data.read2B(ppsLen);
if (ppsLen > 0)
{
_decode(data(0, ppsLen));
}
}
virtual void decodeH265Header(IOBuffer &data)
{
u8 lengthSizeMinusOne = data[22];
lengthSizeMinusOne &= 0x03;
NAL_unit_length = lengthSizeMinusOne;
data >>= 26;
//data.consoleHex();
int vps = 0, sps = 0, pps = 0;
data.read2B(vps);
_decode(data(0, vps));
data >>= vps + 3;
data.read2B(sps);
_decode(data(0, sps));
data >>= sps + 3;
data.read2B(pps);
_decode(data(0, pps));
}
bool isAVCSequence(IOBuffer &data)
{
return data[0] >> 4 == 1 && data[1] == 0; //0AVCSequence Header1AVC NALU2AVC end ofsequence
}
virtual void decode(IOBuffer &data)
{
if (isAVCSequence(data))
{
int codec_id = data[0] & 0x0F;
data >>= 5;
emscripten_log(0, "codec = %d", codec_id);
switch (codec_id)
{
_decode(data(0,ppsLen));
case 7:
decodeH264Header(data);
break;
case 12:
decodeH265Header(data);
break;
default:
emscripten_log(0, "codec not support: %d", codec_id);
break;
}
}
else if (codec_id == 12)
else
{
u8 lengthSizeMinusOne = data[27];
lengthSizeMinusOne &= 0x03;
NAL_unit_length = lengthSizeMinusOne;
data>>=31;
//data.consoleHex();
int vps = 0, sps = 0, pps = 0;
data.read2B(vps);
_decode(data(0, vps));
data >>= vps+3;
data.read2B(sps);
_decode(data(0, sps));
data >>= sps+3;
data.read2B(pps);
_decode(data(0, pps));
data >>= 5;
decodeBody(data);
}
}
virtual void decode(IOBuffer &data)
virtual void decodeBody(IOBuffer &data)
{
int NALUnitLength = 0;
while (data.length > 4)

46
ffmpeg.h

@ -6,7 +6,7 @@ extern "C"
class FFmpeg : public VideoDecoder
{
public:
public:
AVCodec *codec;
AVCodecParserContext *parser;
AVCodecContext *dec_ctx = NULL;
@ -30,47 +30,25 @@ class FFmpeg : public VideoDecoder
free(dec_ctx->extradata);
avcodec_free_context(&dec_ctx);
}
void decodeHeader(IOBuffer& data, int codec_id) override
void decodeH264Header(IOBuffer &data) override
{
codec = avcodec_find_decoder(codec_id == 7 ? AV_CODEC_ID_H264 : AV_CODEC_ID_H265);
emscripten_log(0, "codec = %d,ptr = %d", codec_id, codec);
if (dec_ctx != NULL)
clear();
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
parser = av_parser_init(codec->id);
dec_ctx = avcodec_alloc_context3(codec);
if (codec_id == 7)
{
data >>= 5;
//dec_ctx->extradata = (u8 *)(const u8 *)data;
dec_ctx->extradata_size = data.length;
dec_ctx->extradata = (u8 *)malloc(dec_ctx->extradata_size);
memcpy( dec_ctx->extradata,(const u8 *)data,dec_ctx->extradata_size);
auto ret = avcodec_open2(dec_ctx, codec, NULL);
emscripten_log(0, "avcodec_open2:%d", ret);
}
else
{
// u8 lengthSizeMinusOne = data[27];
// lengthSizeMinusOne &= 0x03;
// NAL_unit_length = lengthSizeMinusOne;
// data.offset = 31 + index;
// int vps=0,sps=0,pps=0;
// data.read2B(vps);
// _decode((const char*)data,vps);
// data>>=vps;
// data>>=3;
// data.read2B(sps);
// _decode((const char*)data,sps);
// data>>=sps;
// data>>=3;
// data.read2B(pps);
// _decode((const char*)data,pps);
}
dec_ctx->extradata_size = data.length;
dec_ctx->extradata = (u8 *)malloc(dec_ctx->extradata_size);
memcpy(dec_ctx->extradata, (const u8 *)data, dec_ctx->extradata_size);
auto ret = avcodec_open2(dec_ctx, codec, NULL);
emscripten_log(0, "avcodec_open2:%d", ret);
}
void decode(IOBuffer&data) override
void decodeBody(IOBuffer &data) override
{
_decode(data);
}
void _decode(IOBuffer data) override
{ //emscripten_log(0, "len:%d", len);
{ //emscripten_log(0, "len:%d", len);
int ret = av_parser_parse2(parser, dec_ctx, &pkt->data, &pkt->size,
(const u8 *)(data), data.length, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
if (ret >= 0 && pkt->size)

6
libde265.h

@ -17,7 +17,7 @@ public:
}
void _decode(IOBuffer data) override
{
de265_push_NAL(h265DecContext, (const unsigned char*)data, data.length, 0, nullptr);
de265_push_NAL(h265DecContext, (const unsigned char *)data, data.length, 0, nullptr);
int more = 1;
while (more)
{
@ -25,8 +25,8 @@ public:
auto err = de265_decode(h265DecContext, &more);
if (err != DE265_OK)
{
if (err!=DE265_ERROR_WAITING_FOR_INPUT_DATA)
emscripten_log(0, "de265_decode:%d", err);
if (err != DE265_ERROR_WAITING_FOR_INPUT_DATA)
emscripten_log(0, "de265_decode:%d", err);
break;
}
const de265_image *img = de265_get_next_picture(h265DecContext);

9
libhevc.h

@ -68,17 +68,17 @@ public:
free((void *)p_yuv[0]);
}
void decodeHeader(IOBuffer&data, int codec_id) override
void decodeH265Header(IOBuffer &data) override
{
CALL_API(ivd_ctl_set_config, "\nError in setting the codec in header decode mode", IVD_CMD_VIDEO_CTL, IVD_CMD_CTL_SETPARAMS, IVD_DECODE_HEADER, STRIDE, IVD_SKIP_NONE, IVD_DISPLAY_FRAME_OUT)
s_video_decode_ip.e_cmd = IVD_CMD_VIDEO_DECODE;
s_video_decode_ip.u4_ts = u4_ip_frm_ts;
s_video_decode_ip.u4_size = sizeof(ivd_video_decode_ip_t);
s_video_decode_op.u4_size = sizeof(ivd_video_decode_op_t);
u8 lengthSizeMinusOne = data[27];
u8 lengthSizeMinusOne = data[22];
lengthSizeMinusOne &= 0x03;
NAL_unit_length = lengthSizeMinusOne;
data >>= 31;
data >>= 26;
int vps = 0, sps = 0, pps = 0;
data.read2B(vps);
s_video_decode_ip.pv_stream_buffer = (void *)data.point();
@ -114,7 +114,8 @@ public:
ret = ihevcd_cxa_api_function(codec_obj, &s_video_decode_ip, &s_video_decode_op);
s_video_decode_ip.u4_num_Bytes -= s_video_decode_op.u4_num_bytes_consumed;
s_video_decode_ip.pv_stream_buffer = (UWORD8 *)s_video_decode_ip.pv_stream_buffer + s_video_decode_op.u4_num_bytes_consumed;
if (ret==IV_SUCCESS)decodeYUV420();
if (ret == IV_SUCCESS)
decodeYUV420();
} while (s_video_decode_ip.u4_num_Bytes);
}
};

38
public/ff_aac.js
File diff suppressed because it is too large
View File

Loading…
Cancel
Save