-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathH264VideoSink.cpp
132 lines (116 loc) · 3.18 KB
/
H264VideoSink.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include "stdafx.h"
#include "H264VideoSink.h"
#include <iostream>
#include <process.h>
#include <cmath>
#include "MediaQueue.h"
#pragma unmanaged
static int frame_count;
/**
Static construtor to create our implemenation of a video size
*/
H264VideoSink* H264VideoSink::createNew(UsageEnvironment& env, MediaSubsession& subsession, char const* streamId) {
return new H264VideoSink(env, subsession, streamId);
}
/**
Singleton constructor
*/
H264VideoSink::H264VideoSink(UsageEnvironment& env, MediaSubsession& subsession, char const* streamId):
MediaSink(env), m_fSubsession(subsession) , m_ready(0)
{
TRACE_INFO("Video sink constructor");
m_fStreamId = strDup(streamId);
m_bufferSize=253440;//2*DUMMY_SINK_RECEIVE_BUFFER_SIZE;
m_fPos = 0;
uint8_t startCode[] = {0x00, 0x00,0x01};
m_buffer = new unsigned char[m_bufferSize];
m_frameQueue=new CMediaQueue(200);
m_decoder=new CVideoDecoder();
AddData(startCode, sizeof(startCode));
InitializeCriticalSection(&m_criticalSection);
m_ready=1;
}
/**
Destructor
*/
H264VideoSink::~H264VideoSink()
{
TRACE_INFO("Cleaning up video sink");
m_ready=0;
if(m_buffer!=NULL)
delete [] m_buffer;
m_buffer = NULL;
m_bufferSize = 0;
if(m_fStreamId!=NULL)
delete [] m_fStreamId;
m_fStreamId = NULL;
if(m_frameQueue!=NULL)
delete m_frameQueue;
m_frameQueue=NULL;
}
/**
Initialize the video buffer with the header information
*/
void H264VideoSink::AddData(uint8_t* aData, int aSize)
{
memcpy(m_buffer + m_fPos, aData, aSize);
m_fPos += aSize;
}
/**
Keep retrieving frames from the source
*/
Boolean H264VideoSink::continuePlaying()
{
if (fSource == NULL)
{
TRACE_ERROR("no source for continue play");
return False;
}
TRACE_DEBUG("continuePlaying. BufferSize=%d",m_bufferSize);
fSource->getNextFrame(m_buffer + m_fPos, m_bufferSize - m_fPos, afterGettingFrame, this, onSourceClosure, this);
return True;
}
/**
Called by the live555 code once we have a frame
*/
void H264VideoSink::afterGettingFrame(void* clientData, unsigned frameSize, unsigned numTruncatedBytes,
struct timeval presentationTime, unsigned durationInMicroseconds)
{
TRACE_DEBUG("afterGettingFrame. FrameSize=%d",frameSize);
H264VideoSink* sink = (H264VideoSink*)clientData;
sink->afterGettingFrame1(frameSize, presentationTime);
if (sink->continuePlaying() == false)
{
TRACE_ERROR("Continue play failed closing source");
sink->onSourceClosure(clientData);
}
}
/**
Prepare the video frame for decoding
*/
void H264VideoSink::afterGettingFrame1(unsigned frameSize, struct timeval presentationTime)
{
int got_frame = 0;
unsigned int size = frameSize;
unsigned char *pBuffer = m_buffer + m_fPos;
uint8_t* data = (uint8_t*)pBuffer;
uint8_t startCode4[] = {0x00, 0x00, 0x00, 0x01};
uint8_t startCode3[] = {0x00, 0x00, 0x01};
FrameInfo *frame=NULL;
if(size<4){
return;
}
if(memcmp(startCode3, pBuffer, sizeof(startCode3)) == 0)
{
data += 3;
}else if(memcmp(startCode4, pBuffer, sizeof(startCode4)) == 0){
data += 4;
}else{
pBuffer -= 3;
size += 3;
}
// send the frame out to the decoder
frame=m_decoder->DecodeFrame(pBuffer, size);
if(frame!=NULL)
m_frameQueue->put(frame);
}