Commit cc38b35a authored by François Grisez's avatar François Grisez
Browse files

Rewrite byteStreamToNalus() and nalusToByteStream()

parent 2579160b
......@@ -29,6 +29,7 @@
#include "h26x-utils.h"
using namespace mediastreamer;
using namespace std;
extern "C" {
......
......@@ -17,6 +17,11 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <cstdint>
#include <cstring>
#include <stdexcept>
#include <vector>
#include "h26x-utils.h"
using namespace std;
......@@ -47,94 +52,66 @@ void byteStreamToNalus(const std::vector<uint8_t> &byteStream, MSQueue *out) {
byteStreamToNalus(byteStream.data(), byteStream.size(), out);
}
static void push_nalu(const uint8_t *begin, const uint8_t *end, MSQueue *nalus) {
unsigned ecount = 0;
const uint8_t *src = begin;
size_t nalu_len = (end - begin);
uint8_t nalu_byte = *src++;
mblk_t *m = allocb(nalu_len, 0);
// Removal of the 3 in a 003x sequence
// This emulation prevention byte is normally part of a NAL unit.
/* H.264 standard sys in par 7.4.1 page 58
* emulation_prevention_three_byte is a byte equal to 0x03.
* When an emulation_prevention_three_byte is present in a NAL unit, it shall be discarded by the decoding process.
* Within the NAL unit, the following three-byte sequence shall not occur at any byte-aligned position: 0x000000, 0x000001, 0x00002
*/
*m->b_wptr++ = nalu_byte;
while (src < end - 3) {
if (src[0] == 0 && src[1] == 0 && src[2] == 3) {
*m->b_wptr++ = 0;
*m->b_wptr++ = 0;
// drop the emulation_prevention_three_byte
src += 3;
++ecount;
continue;
}
*m->b_wptr++ = *src++;
}
*m->b_wptr++ = *src++;
*m->b_wptr++ = *src++;
*m->b_wptr++ = *src++;
ms_queue_put(nalus, m);
}
void byteStreamToNalus(const uint8_t *byteStream, size_t size, MSQueue *out) {
size_t i;
const uint8_t *p, *begin = NULL;
int zeroes = 0;
for (i = 0, p = byteStream; i < size; ++i) {
if (*p == 0) {
++zeroes;
} else if (zeroes >= 2 && *p == 1) {
if (begin) {
push_nalu(begin, p - zeroes, out);
vector<uint8_t> buffer;
const uint8_t *end = byteStream + size;
for (const uint8_t *it = byteStream; it != end;) {
buffer.resize(0);
int leadingZero = 0;
while (it != end && *it == 0) {
leadingZero++;
it++;
}
if (it == end) break;
if (leadingZero < 2 || *it++ != 1) throw invalid_argument("no starting sequence found in H26x byte stream");
while (it != end) {
if (it + 2 < end && it[0] == 0 && it[1] == 0) {
if (it[2] == 0 || it[2] == 1) break;
else if (it[2] == 3) {
buffer.push_back(0);
buffer.push_back(0);
it += 3;
continue;
}
}
begin = p + 1;
} else zeroes = 0;
++p;
buffer.push_back(*it++);
}
mblk_t *nalu = allocb(buffer.size(), 0);
memcpy(nalu->b_wptr, buffer.data(), buffer.size());
nalu->b_wptr += buffer.size();
ms_queue_put(out, nalu);
}
if (begin) push_nalu(begin, p, out);
}
void nalusToByteStream(MSQueue *nalus, std::vector<uint8_t> &bytestream) {
bool start_picture = true;
bytestream.resize(0);
void nalusToByteStream(MSQueue *nalus, std::vector<uint8_t> &byteStream) {
bool startPicture = true;
byteStream.resize(0);
while (mblk_t *im = ms_queue_get(nalus)) {
const uint8_t *src = im->b_rptr;
if (src[0] == 0 && src[1] == 0 && src[2] == 0 && src[3] == 1) {
while (src != im->b_wptr) {
bytestream.push_back(*src++);
}
} else {
if (start_picture) {
bytestream.push_back(0);
start_picture = false;
}
/*prepend nal marker*/
bytestream.push_back(0);
bytestream.push_back(0);
bytestream.push_back(1);
bytestream.push_back(*src++);
while (src < (im->b_wptr - 3)) {
if (src[0] == 0 && src[1] == 0 && src[2] < 3) {
bytestream.push_back(0);
bytestream.push_back(0);
bytestream.push_back(3);
src += 2;
}
if (startPicture) {
// starting picture extra zero byte
byteStream.push_back(0);
startPicture = false;
}
bytestream.push_back(*src++);
// starting NALu marker
byteStream.push_back(0);
byteStream.push_back(0);
byteStream.push_back(1);
// copy NALu content
for (const uint8_t *src = im->b_rptr; src < im->b_wptr;) {
if (src+2 < im->b_wptr && src[0] == 0 && src[1] == 0 && (src[2] == 0 || src[2] == 1)) {
byteStream.push_back(0);
byteStream.push_back(0);
byteStream.push_back(3); // emulation prevention three byte
byteStream.push_back(src[2]);
src += 3;
} else {
byteStream.push_back(*src++);
}
bytestream.push_back(*src++);
bytestream.push_back(*src++);
bytestream.push_back(*src++);
}
freemsg(im);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment