Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(195)

Side by Side Diff: webrtc/modules/video_coding/h264_sps_pps_tracker.cc

Issue 2466993003: H264SpsPpsTracker class which keep tracks of SPS/PPS. (Closed)
Patch Set: Free copied data Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/modules/video_coding/h264_sps_pps_tracker.h"
12
13 #include <string>
14
15 #include "webrtc/base/checks.h"
16 #include "webrtc/base/logging.h"
17 #include "webrtc/common_video/h264/h264_common.h"
18 #include "webrtc/modules/video_coding/frame_object.h"
19 #include "webrtc/modules/video_coding/packet_buffer.h"
20
21 namespace webrtc {
22 namespace video_coding {
23
24 namespace {
25 const uint8_t start_code_h264[] = {0, 0, 0, 1};
26 } // namespace
27
28 bool H264SpsPpsTracker::CopyAndFixBitstream(VCMPacket* packet) {
29 RTC_DCHECK(packet->codec == kVideoCodecH264);
30
31 const uint8_t* data = packet->dataPtr;
32 const size_t data_size = packet->sizeBytes;
33 const RTPVideoHeader& video_header = packet->video_header;
34 const RTPVideoHeaderH264& codec_header = video_header.codecHeader.H264;
35
36 // Packets that only contains SPS/PPS are not decodable by themselves, and
37 // to avoid frames being created containing only these two nalus we don't
38 // insert them into the PacketBuffer. Instead we save the SPS/PPS and
39 // prepend the bitstream of first packet of an IDR referring to the
40 // corresponding SPS/PPS id.
41 bool insert_packet = codec_header.nalus_length == 0 ? true : false;
42
43 int pps_id = -1;
44 size_t required_size = 0;
45 for (size_t i = 0; i < codec_header.nalus_length; ++i) {
46 const NaluInfo& nalu = codec_header.nalus[i];
47 switch (nalu.type) {
48 case H264::NaluType::kSps: {
49 // Save SPS.
50 sps_data_[nalu.sps_id].size = nalu.size;
51 sps_data_[nalu.sps_id].data.reset(new uint8_t[nalu.size]);
52 memcpy(sps_data_[nalu.sps_id].data.get(), data + nalu.offset,
53 nalu.size);
54 break;
55 }
56 case H264::NaluType::kPps: {
57 // Save PPS.
58 pps_data_[nalu.pps_id].sps_id = nalu.sps_id;
59 pps_data_[nalu.pps_id].size = nalu.size;
60 pps_data_[nalu.pps_id].data.reset(new uint8_t[nalu.size]);
61 memcpy(pps_data_[nalu.pps_id].data.get(), data + nalu.offset,
62 nalu.size);
63 break;
64 }
65 case H264::NaluType::kIdr: {
66 // If this is the first packet of an IDR, make sure we have the required
67 // SPS/PPS and also calculate how much extra space we need in the buffer
68 // to prepend the SPS/PPS to the bitstream with start codes.
69 if (video_header.isFirstPacket) {
70 if (nalu.pps_id == -1) {
71 LOG(LS_WARNING) << "No PPS id in IDR nalu.";
72 return false;
73 }
74
75 auto pps = pps_data_.find(nalu.pps_id);
76 if (pps == pps_data_.end()) {
77 LOG(LS_WARNING) << "No PPS with id << " << nalu.pps_id
78 << " received";
79 return false;
80 }
81
82 auto sps = sps_data_.find(pps->second.sps_id);
83 if (sps == sps_data_.end()) {
84 LOG(LS_WARNING) << "No SPS with id << "
85 << pps_data_[nalu.pps_id].sps_id << " received";
86 return false;
87 }
88
89 pps_id = nalu.pps_id;
90 required_size += pps->second.size + sizeof(start_code_h264);
91 required_size += sps->second.size + sizeof(start_code_h264);
92 }
93 FALLTHROUGH();
94 }
95 default: {
96 // Something other than an SPS/PPS nalu in this packet, then it should
97 // be inserted into the PacketBuffer.
98 insert_packet = true;
99 }
100 }
101 }
102
103 if (!insert_packet)
104 return false;
105
106 // Calculate how much space we need for the rest of the bitstream.
107 if (codec_header.packetization_type == kH264StapA) {
108 const uint8_t* nalu_ptr = data + 1;
109 while (nalu_ptr < data + data_size) {
110 RTC_DCHECK(video_header.isFirstPacket);
111 required_size += sizeof(start_code_h264);
112
113 // The first two bytes describe the length of a segment.
114 uint16_t segment_length = nalu_ptr[0] << 8 | nalu_ptr[1];
115 nalu_ptr += 2;
116
117 required_size += segment_length;
118 nalu_ptr += segment_length;
119 }
120 } else {
121 if (video_header.isFirstPacket)
122 required_size += sizeof(start_code_h264);
123 required_size += data_size;
124 }
125
126 // Then we copy to the new buffer.
127 uint8_t* buffer = new uint8_t[required_size];
128 uint8_t* insert_at = buffer;
129
130 // If pps_id != -1 then we have the SPS/PPS and they should be prepended
131 // to the bitstream with start codes inserted.
132 if (pps_id != -1) {
133 // Insert SPS.
134 memcpy(insert_at, start_code_h264, sizeof(start_code_h264));
135 insert_at += sizeof(start_code_h264);
136 memcpy(insert_at, sps_data_[pps_data_[pps_id].sps_id].data.get(),
137 sps_data_[pps_data_[pps_id].sps_id].size);
138 insert_at += sps_data_[pps_data_[pps_id].sps_id].size;
139
140 // Insert PPS.
141 memcpy(insert_at, start_code_h264, sizeof(start_code_h264));
142 insert_at += sizeof(start_code_h264);
143 memcpy(insert_at, pps_data_[pps_id].data.get(), pps_data_[pps_id].size);
144 insert_at += pps_data_[pps_id].size;
145 }
146
147 // Copy the rest of the bitstream and insert start codes.
148 if (codec_header.packetization_type == kH264StapA) {
149 const uint8_t* nalu_ptr = data + 1;
150 while (nalu_ptr < data + data_size) {
151 memcpy(insert_at, start_code_h264, sizeof(start_code_h264));
152 insert_at += sizeof(start_code_h264);
153
154 // The first two bytes describe the length of a segment.
155 uint16_t segment_length = nalu_ptr[0] << 8 | nalu_ptr[1];
156 nalu_ptr += 2;
157
158 size_t copy_end = nalu_ptr - data + segment_length;
159 if (copy_end > data_size) {
160 delete[] buffer;
161 return false;
162 }
163
164 memcpy(insert_at, nalu_ptr, segment_length);
165 insert_at += segment_length;
166 nalu_ptr += segment_length;
167 }
168 } else {
169 if (video_header.isFirstPacket) {
170 memcpy(insert_at, start_code_h264, sizeof(start_code_h264));
171 insert_at += sizeof(start_code_h264);
172 }
173 memcpy(insert_at, data, data_size);
174 }
175
176 packet->dataPtr = buffer;
177 packet->sizeBytes = required_size;
178 return true;
179 }
180
181 } // namespace video_coding
182 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/video_coding/h264_sps_pps_tracker.h ('k') | webrtc/modules/video_coding/h264_sps_pps_tracker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698