bool xtr_hevc_c::write_nal(binary const *data, size_t &pos, size_t data_size, size_t write_nal_size_size) { if (write_nal_size_size > data_size) return false; auto nal_size = get_uint_be(&data[pos], write_nal_size_size); pos += write_nal_size_size; if ((pos + nal_size) > data_size) { mxwarn(boost::format(Y("Track %1%: NAL too big. Size according to header field: %2%, available bytes in packet: %3%. This NAL is defect and will be skipped.\n")) % m_tid % nal_size % (data_size - pos)); return false; } auto nal_unit_type = (data[pos] >> 1) & 0x3f; auto start_code_size = m_first_nalu || (HEVC_NALU_TYPE_VIDEO_PARAM == nal_unit_type) || (HEVC_NALU_TYPE_SEQ_PARAM == nal_unit_type) || (HEVC_NALU_TYPE_PIC_PARAM == nal_unit_type) ? 4 : 3; m_first_nalu = false; m_out->write(ms_start_code + (4 - start_code_size), start_code_size); m_out->write(data + pos, nal_size); pos += nal_size; return true; }
void mpeg4_p10_video_packetizer_c::change_nalu_size_len(packet_cptr packet) { unsigned char *src = packet->data->get_buffer(); int size = packet->data->get_size(); if (!src || !size) return; std::vector<int> nalu_sizes; int src_pos = 0; // Find all NALU sizes in this packet. while (src_pos < size) { if ((size - src_pos) < m_nalu_size_len_src) break; int nalu_size = get_uint_be(&src[src_pos], m_nalu_size_len_src); nalu_size = std::min<int>(nalu_size, size - src_pos - m_nalu_size_len_src); if (nalu_size > m_max_nalu_size) mxerror_tid(m_ti.m_fname, m_ti.m_id, boost::format(Y("The chosen NALU size length of %1% is too small. Try using '4'.\n")) % m_nalu_size_len_dst); src_pos += m_nalu_size_len_src + nalu_size; nalu_sizes.push_back(nalu_size); } // Allocate memory if the new NALU size length is greater // than the previous one. Otherwise reuse the existing memory. if (m_nalu_size_len_dst > m_nalu_size_len_src) { int new_size = size + nalu_sizes.size() * (m_nalu_size_len_dst - m_nalu_size_len_src); packet->data = memory_cptr(new memory_c((unsigned char *)safemalloc(new_size), new_size, true)); } // Copy the NALUs and write the new sized length field. unsigned char *dst = packet->data->get_buffer(); src_pos = 0; int dst_pos = 0; size_t i; for (i = 0; nalu_sizes.size() > i; ++i) { int nalu_size = nalu_sizes[i]; put_uint_be(&dst[dst_pos], nalu_size, m_nalu_size_len_dst); memmove(&dst[dst_pos + m_nalu_size_len_dst], &src[src_pos + m_nalu_size_len_src], nalu_size); src_pos += m_nalu_size_len_src + nalu_size; dst_pos += m_nalu_size_len_dst + nalu_size; } packet->data->set_size(dst_pos); }
void mpeg4_p10_video_packetizer_c::remove_filler_nalus(memory_c &data) const { auto ptr = data.get_buffer(); auto total_size = data.get_size(); auto idx = 0u; while ((idx + m_nalu_size_len_dst) < total_size) { auto nalu_size = get_uint_be(&ptr[idx], m_nalu_size_len_dst) + m_nalu_size_len_dst; if ((idx + nalu_size) > total_size) break; if (ptr[idx + m_nalu_size_len_dst] == NALU_TYPE_FILLER_DATA) { memmove(&ptr[idx], &ptr[idx + nalu_size], total_size - idx - nalu_size); total_size -= nalu_size; continue; } idx += nalu_size; } data.resize(total_size); }
file_status_e avi_reader_c::read_video() { if (m_video_frames_read >= m_max_video_frames) return flush_packetizer(m_vptzr); memory_cptr chunk; int key = 0; int old_video_frames_read = m_video_frames_read; int size, num_read; int dropped_frames_here = 0; do { size = AVI_frame_size(m_avi, m_video_frames_read); chunk = memory_c::alloc(size); num_read = AVI_read_frame(m_avi, reinterpret_cast<char *>(chunk->get_buffer()), &key); ++m_video_frames_read; if (0 > num_read) { // Error reading the frame: abort m_video_frames_read = m_max_video_frames; return flush_packetizer(m_vptzr); } else if (0 == num_read) ++dropped_frames_here; } while ((0 == num_read) && (m_video_frames_read < m_max_video_frames)); if (0 == num_read) // This is only the case if the AVI contains dropped frames only. return flush_packetizer(m_vptzr); size_t i; for (i = m_video_frames_read; i < m_max_video_frames; ++i) { if (0 != AVI_frame_size(m_avi, i)) break; int dummy_key; AVI_read_frame(m_avi, nullptr, &dummy_key); ++dropped_frames_here; ++m_video_frames_read; } int64_t timestamp = static_cast<int64_t>(static_cast<int64_t>(old_video_frames_read) * 1000000000ll / m_fps); int64_t duration = static_cast<int64_t>(static_cast<int64_t>(dropped_frames_here + 1) * 1000000000ll / m_fps); m_dropped_video_frames += dropped_frames_here; // AVC with framed packets (without NALU start codes but with length fields) // or non-AVC video track? if (0 >= m_avc_nal_size_size) PTZR(m_vptzr)->process(new packet_t(chunk, timestamp, duration, key ? VFT_IFRAME : VFT_PFRAMEAUTOMATIC, VFT_NOBFRAME)); else { // AVC video track without NALU start codes. Re-frame with NALU start codes. int offset = 0; while ((offset + m_avc_nal_size_size) < num_read) { int nalu_size = get_uint_be(chunk->get_buffer() + offset, m_avc_nal_size_size); offset += m_avc_nal_size_size; if ((offset + nalu_size) > num_read) break; memory_cptr nalu = memory_c::alloc(4 + nalu_size); put_uint32_be(nalu->get_buffer(), NALU_START_CODE); memcpy(nalu->get_buffer() + 4, chunk->get_buffer() + offset, nalu_size); offset += nalu_size; PTZR(m_vptzr)->process(new packet_t(nalu, timestamp, duration, key ? VFT_IFRAME : VFT_PFRAMEAUTOMATIC, VFT_NOBFRAME)); } } m_bytes_processed += num_read; return m_video_frames_read >= m_max_video_frames ? flush_packetizer(m_vptzr) : FILE_STATUS_MOREDATA; }