diff --git a/src/input/r_aac.cpp b/src/input/r_aac.cpp index a90215f09..f6ba117a6 100644 --- a/src/input/r_aac.cpp +++ b/src/input/r_aac.cpp @@ -172,7 +172,8 @@ aac_reader_c::read(generic_packetizer_c *) { return 0; } - aacpacketizer->process(chunk, nread); + memory_c mem(chunk, nread, false); + aacpacketizer->process(mem); bytes_processed += nread; return EMOREDATA; diff --git a/src/input/r_ac3.cpp b/src/input/r_ac3.cpp index d8fcd6041..ccb1af6b8 100644 --- a/src/input/r_ac3.cpp +++ b/src/input/r_ac3.cpp @@ -113,7 +113,8 @@ ac3_reader_c::read(generic_packetizer_c *) { return 0; } - ac3packetizer->process(chunk, nread); + memory_c mem(chunk, nread, false); + ac3packetizer->process(mem); bytes_processed += nread; return EMOREDATA; diff --git a/src/input/r_avi.cpp b/src/input/r_avi.cpp index baef4e2a4..f79081c71 100644 --- a/src/input/r_avi.cpp +++ b/src/input/r_avi.cpp @@ -547,8 +547,10 @@ avi_reader_c::read(generic_packetizer_c *ptzr) { debug_leave("AVI_read_frame"); #endif if (nread < 0) { - vpacketizer->process(old_chunk, old_nread, -1, -1, + memory_c mem(old_chunk, old_nread, true); + vpacketizer->process(mem, -1, -1, old_key ? VFT_IFRAME : VFT_PFRAMEAUTOMATIC); + old_chunk = NULL; mxwarn(PFX "Reading frame number %d resulted in an error. " "Aborting this track.\n", frames); frames = maxframes + 1; @@ -569,8 +571,10 @@ avi_reader_c::read(generic_packetizer_c *ptzr) { } duration = (int64_t)(1000000000.0 * frames_read / fps); if (nread > 0) { - vpacketizer->process(old_chunk, old_nread, -1, duration, + memory_c mem(old_chunk, old_nread, true); + vpacketizer->process(mem, -1, duration, old_key ? VFT_IFRAME : VFT_PFRAMEAUTOMATIC); + old_chunk = NULL; if (! last_frame) { if (old_chunk != NULL) safefree(old_chunk); @@ -578,7 +582,8 @@ avi_reader_c::read(generic_packetizer_c *ptzr) { old_key = key; old_nread = nread; } else if (nread > 0) { - vpacketizer->process(chunk, nread, -1, duration, + memory_c mem(chunk, nread, false); + vpacketizer->process(mem, -1, duration, key ? VFT_IFRAME : VFT_PFRAMEAUTOMATIC); } } @@ -617,7 +622,8 @@ avi_reader_c::read(generic_packetizer_c *ptzr) { debug_leave("aviclasses->Read() audio"); demuxer->frame += blread; if (result == S_OK) { - demuxer->packetizer->process(chunk, nread); + memory_c mem(chunk, nread, false); + demuxer->packetizer->process(mem); need_more_data = demuxer->frame < demuxer->maxframes; } else demuxer->frame = demuxer->maxframes; @@ -639,7 +645,8 @@ avi_reader_c::read(generic_packetizer_c *ptzr) { if (nread > 0) { if (nread >= size) need_more_data = true; - demuxer->packetizer->process(chunk, nread); + memory_c mem(chunk, nread, false); + demuxer->packetizer->process(mem); } #endif diff --git a/src/input/r_dts.cpp b/src/input/r_dts.cpp index 69c674fc2..0925f64dc 100644 --- a/src/input/r_dts.cpp +++ b/src/input/r_dts.cpp @@ -108,7 +108,8 @@ dts_reader_c::read(generic_packetizer_c *) { return 0; } - dtspacketizer->process(chunk, nread); + memory_c mem(chunk, nread, false); + dtspacketizer->process(mem); bytes_processed += nread; return EMOREDATA; diff --git a/src/input/r_flac.cpp b/src/input/r_flac.cpp index 79d8203ce..da2aa013f 100644 --- a/src/input/r_flac.cpp +++ b/src/input/r_flac.cpp @@ -134,7 +134,6 @@ flac_reader_c::flac_reader_c(track_info_c *nti) } packetizer = new flac_packetizer_c(this, sample_rate, channels, bits_per_sample, buf, block_size, ti); - packetizer->duplicate_data_on_add(false); safefree(buf); } catch (error_c &error) { mxerror(FPFX "could not initialize the FLAC packetizer.\n"); @@ -253,9 +252,9 @@ flac_reader_c::read(generic_packetizer_c *) { packetizer->flush(); return 0; } - packetizer->process(buf, current_block->len, samples * 1000000000 / - sample_rate, current_block->samples * 1000000000 / - sample_rate); + memory_c mem(buf, current_block->len, true); + packetizer->process(mem, samples * 1000000000 / sample_rate, + current_block->samples * 1000000000 / sample_rate); samples += current_block->samples; current_block++; diff --git a/src/input/r_matroska.cpp b/src/input/r_matroska.cpp index 616b67ca0..aae8671e3 100644 --- a/src/input/r_matroska.cpp +++ b/src/input/r_matroska.cpp @@ -186,6 +186,8 @@ kax_reader_c::~kax_reader_c() { delete saved_l1; if (in != NULL) delete in; + if (es != NULL) + delete es; if (segment != NULL) delete segment; } @@ -1790,9 +1792,10 @@ kax_reader_c::read(generic_packetizer_c *) { for (i = 0; i < (int)block->NumberFrames(); i++) { DataBuffer &data = block->GetBuffer(i); + memory_c mem((unsigned char *)data.Buffer(), data.Size(), + false); ((passthrough_packetizer_c *)block_track->packetizer)-> - process((unsigned char *)data.Buffer(), data.Size(), - last_timecode, block_duration, + process(mem, last_timecode, block_duration, block_bref, block_fref, duration != NULL); } @@ -1844,21 +1847,19 @@ kax_reader_c::read(generic_packetizer_c *) { lines = (char *)safemalloc(re_size + 1); lines[re_size] = 0; memcpy(lines, re_buffer, re_size); - block_track->packetizer->process((unsigned char *)lines, 0, - (int64_t)last_timecode, - block_duration, - block_bref, - block_fref); - safefree(lines); + memory_c mem((unsigned char *)lines, 0, true); + block_track->packetizer-> + process(mem, (int64_t)last_timecode, block_duration, + block_bref, block_fref); + if (re_modified) + safefree(re_buffer); } - } else - block_track->packetizer->process(re_buffer, re_size, - (int64_t)last_timecode, - block_duration, - block_bref, - block_fref); - if (re_modified) - safefree(re_buffer); + } else { + memory_c mem(re_buffer, re_size, re_modified); + block_track->packetizer-> + process(mem, (int64_t)last_timecode, block_duration, + block_bref, block_fref); + } } block_track->previous_timecode = (int64_t)last_timecode; diff --git a/src/input/r_mp3.cpp b/src/input/r_mp3.cpp index 3504cd31d..804540c8a 100644 --- a/src/input/r_mp3.cpp +++ b/src/input/r_mp3.cpp @@ -126,7 +126,8 @@ mp3_reader_c::read(generic_packetizer_c *) { return 0; } - mp3packetizer->process(chunk, nread); + memory_c mem(chunk, nread, false); + mp3packetizer->process(mem); bytes_processed += nread; return EMOREDATA; diff --git a/src/input/r_ogm.cpp b/src/input/r_ogm.cpp index 853a9d2d5..1bb856121 100644 --- a/src/input/r_ogm.cpp +++ b/src/input/r_ogm.cpp @@ -345,7 +345,7 @@ ogm_reader_c::~ogm_reader_c() { delete dmx; } safefree(sdemuxers); - ti->private_data = NULL; + delete mm_io; } ogm_demuxer_t * @@ -903,16 +903,17 @@ ogm_reader_c::process_page(ogg_page *og) { if (dmx->units_processed <= dmx->flac_header_packets) continue; for (i = 0; i < (int)dmx->nh_packet_data.size(); i++) { - dmx->packetizer->process(dmx->nh_packet_data[i], - dmx->nh_packet_sizes[i], 0); - safefree(dmx->nh_packet_data[i]); + memory_c mem(dmx->nh_packet_data[i], dmx->nh_packet_sizes[i], true); + dmx->packetizer->process(mem, 0); } dmx->nh_packet_data.clear(); - if (dmx->last_granulepos == -1) - dmx->packetizer->process(op.packet, op.bytes, -1); - else { - dmx->packetizer->process(op.packet, op.bytes, dmx->last_granulepos * - 1000000000 / dmx->vorbis_rate); + if (dmx->last_granulepos == -1) { + memory_c mem(op.packet, op.bytes, false); + dmx->packetizer->process(mem, -1); + } else { + memory_c mem(op.packet, op.bytes, false); + dmx->packetizer->process(mem, dmx->last_granulepos * 1000000000 / + dmx->vorbis_rate); dmx->last_granulepos = ogg_page_granulepos(og); } @@ -938,8 +939,8 @@ ogm_reader_c::process_page(ogg_page *og) { ((*op.packet & 3) != PACKET_TYPE_COMMENT)) { if (dmx->stype == OGM_STREAM_TYPE_VIDEO) { - dmx->packetizer->process(&op.packet[hdrlen + 1], op.bytes - 1 - hdrlen, - -1, -1, + memory_c mem(&op.packet[hdrlen + 1], op.bytes - 1 - hdrlen, false); + dmx->packetizer->process(mem, -1, -1, (*op.packet & PACKET_IS_SYNCPOINT ? VFT_IFRAME : VFT_PFRAMEAUTOMATIC)); dmx->units_processed += (hdrlen > 0 ? lenbytes : 1); @@ -948,17 +949,19 @@ ogm_reader_c::process_page(ogg_page *og) { dmx->units_processed++; if (((op.bytes - 1 - hdrlen) > 2) || ((op.packet[hdrlen + 1] != ' ') && - (op.packet[hdrlen + 1] != 0) && !iscr(op.packet[hdrlen + 1]))) - dmx->packetizer->process(&op.packet[hdrlen + 1], op.bytes - 1 - - hdrlen, ogg_page_granulepos(og) * 1000000, + (op.packet[hdrlen + 1] != 0) && !iscr(op.packet[hdrlen + 1]))) { + memory_c mem(&op.packet[hdrlen + 1], op.bytes - 1 - hdrlen, false); + dmx->packetizer->process(mem, ogg_page_granulepos(og) * 1000000, (int64_t)lenbytes * 1000000); + } } else if (dmx->stype == OGM_STREAM_TYPE_VORBIS) { - dmx->packetizer->process(op.packet, op.bytes); + memory_c mem(op.packet, op.bytes, false); + dmx->packetizer->process(mem); } else { - dmx->packetizer->process(&op.packet[hdrlen + 1], - op.bytes - 1 - hdrlen); + memory_c mem(&op.packet[hdrlen + 1], op.bytes - 1 - hdrlen, false); + dmx->packetizer->process(mem); dmx->units_processed += op.bytes - 1; } } diff --git a/src/input/r_qtmp4.cpp b/src/input/r_qtmp4.cpp index 21e012d0e..9cfe74971 100644 --- a/src/input/r_qtmp4.cpp +++ b/src/input/r_qtmp4.cpp @@ -878,9 +878,9 @@ qtmp4_reader_c::read(generic_packetizer_c *ptzr) { dmx->avg_duration = (dmx->avg_duration * dmx->pos + duration) / (dmx->pos + 1); - dmx->packetizer->process(buffer, frame_size, timecode, duration, - is_keyframe ? VFT_IFRAME : - VFT_PFRAMEAUTOMATIC); + memory_c mem(buffer, frame_size, true); + dmx->packetizer->process(mem, timecode, duration, is_keyframe ? + VFT_IFRAME : VFT_PFRAMEAUTOMATIC); dmx->pos++; if (dmx->pos < dmx->chunk_table_len) @@ -926,9 +926,9 @@ qtmp4_reader_c::read(generic_packetizer_c *ptzr) { return 0; } - dmx->packetizer->process(buffer, frame_size, timecode, duration, - is_keyframe ? VFT_IFRAME : - VFT_PFRAMEAUTOMATIC); + memory_c mem(buffer, frame_size, true); + dmx->packetizer->process(mem, timecode, duration, is_keyframe ? + VFT_IFRAME : VFT_PFRAMEAUTOMATIC); dmx->pos++; if (dmx->pos < dmx->sample_table_len) chunks_left = true; @@ -1072,8 +1072,6 @@ qtmp4_reader_c::create_packetizer(int64_t tid) { dmx->v_height, false, ti); ti->private_data = NULL; - dmx->packetizer->duplicate_data_on_add(false); - mxinfo("+-> Using the video packetizer for track %u (FourCC: %.4s).\n", dmx->id, dmx->fourcc); @@ -1089,7 +1087,6 @@ qtmp4_reader_c::create_packetizer(int64_t tid) { ptzr->set_audio_sampling_freq(dmx->a_samplerate); ptzr->set_audio_channels(dmx->a_channels); ptzr->set_audio_bit_depth(dmx->a_bitdepth); - ptzr->duplicate_data_on_add(false); if (verbose) mxinfo("+-> Using generic audio output module for stream " @@ -1112,7 +1109,6 @@ qtmp4_reader_c::create_packetizer(int64_t tid) { dmx->packetizer = new aac_packetizer_c(this, AAC_ID_MPEG4, profile, sample_rate, channels, ti, false, true); - dmx->packetizer->duplicate_data_on_add(false); if (sbraac) dmx->packetizer-> set_audio_output_sampling_freq(output_sample_rate); @@ -1130,7 +1126,6 @@ qtmp4_reader_c::create_packetizer(int64_t tid) { dmx->a_channels, dmx->a_bitdepth, ti, (dmx->a_bitdepth > 8) && (dmx->fourcc[0] == 't')); - dmx->packetizer->duplicate_data_on_add(false); if (verbose) mxinfo("+-> Using PCM output module for stream %u.\n", dmx->id); diff --git a/src/input/r_real.cpp b/src/input/r_real.cpp index 97aeb0b44..0b0285cc0 100644 --- a/src/input/r_real.cpp +++ b/src/input/r_real.cpp @@ -261,7 +261,6 @@ real_reader_c::create_packetizer(int64_t tid) { int i; real_demuxer_t *dmx; rmff_track_t *track; - bool duplicate_data; dmx = find_demuxer(tid); if (dmx == NULL) @@ -272,7 +271,6 @@ real_reader_c::create_packetizer(int64_t tid) { ti->id = track->id; ti->private_data = dmx->private_data; ti->private_size = dmx->private_size; - duplicate_data = false; if (track->type == RMFF_TRACK_TYPE_VIDEO) { char buffer[20]; @@ -369,7 +367,6 @@ real_reader_c::create_packetizer(int64_t tid) { "for this input file if the file actually contains SBR AAC. " "The file will be muxed in the WRONG way otherwise. Also " "read mkvmerge's documentation.\n", track->id); - duplicate_data = true; } else { ptzr = new passthrough_packetizer_c(this, ti); @@ -392,8 +389,6 @@ real_reader_c::create_packetizer(int64_t tid) { "%u (FourCC: %s).\n", track->id, dmx->fourcc); } } - - dmx->packetizer->duplicate_data_on_add(duplicate_data); } } @@ -468,12 +463,12 @@ real_reader_c::read(generic_packetizer_c *) { } chunk = (unsigned char *)safemalloc(size); + memory_c mem(chunk, size, true); frame = rmff_read_next_frame(file, chunk); if (frame == NULL) { if (file->num_packets_read < file->num_packets_in_chunk) mxwarn(PFX "%s: File contains fewer frames than expected or is " "corrupt after frame %u.\n", ti->fname, file->num_packets_read); - safefree(chunk); return finish(); } @@ -484,15 +479,14 @@ real_reader_c::read(generic_packetizer_c *) { return EMOREDATA; } - if (dmx->track->type == RMFF_TRACK_TYPE_VIDEO) { - assemble_packet(dmx, chunk, size, timecode, (frame->flags & 2) == 2); - safefree(chunk); + if (dmx->track->type == RMFF_TRACK_TYPE_VIDEO) + assemble_video_packet(dmx, mem, timecode, (frame->flags & 2) == 2); - } else if (dmx->is_aac) - deliver_aac_frames(dmx, chunk, size); + else if (dmx->is_aac) + deliver_aac_frames(dmx, mem); else - queue_audio_frames(dmx, chunk, size, timecode, frame->flags); + queue_audio_frames(dmx, mem, timecode, frame->flags); rmff_release_frame(frame); @@ -501,32 +495,31 @@ real_reader_c::read(generic_packetizer_c *) { void real_reader_c::queue_one_audio_frame(real_demuxer_t *dmx, - unsigned char *chunk, - uint32_t length, + memory_c &mem, uint64_t timecode, uint32_t flags) { rv_segment_t segment; - segment.data = chunk; - segment.size = length; + segment.data = mem.data; + segment.size = mem.size; + mem.lock(); segment.offset = flags; dmx->segments->push_back(segment); dmx->c_timecode = timecode; mxverb(2, "enqueueing one for %u/'%s' length %u timecode %llu flags " - "0x%08x\n", dmx->track->id, ti->fname, length, timecode, flags); + "0x%08x\n", dmx->track->id, ti->fname, mem.size, timecode, flags); } void real_reader_c::queue_audio_frames(real_demuxer_t *dmx, - unsigned char *chunk, - uint32_t length, + memory_c &mem, uint64_t timecode, uint32_t flags) { // Enqueue the packets if no packets are in the queue or if the current // packet's timecode is the same as the timecode of those before. if ((dmx->segments->size() == 0) || (dmx->c_timecode == timecode)) { - queue_one_audio_frame(dmx, chunk, length, timecode, flags); + queue_one_audio_frame(dmx, mem, timecode, flags); return; } @@ -534,11 +527,12 @@ real_reader_c::queue_audio_frames(real_demuxer_t *dmx, deliver_audio_frames(dmx, (timecode - dmx->c_timecode) / dmx->segments->size()); // Enqueue this packet. - queue_one_audio_frame(dmx, chunk, length, timecode, flags); + queue_one_audio_frame(dmx, mem, timecode, flags); } void -real_reader_c::deliver_audio_frames(real_demuxer_t *dmx, uint64_t duration) { +real_reader_c::deliver_audio_frames(real_demuxer_t *dmx, + uint64_t duration) { uint32_t i; rv_segment_t segment; @@ -550,8 +544,8 @@ real_reader_c::deliver_audio_frames(real_demuxer_t *dmx, uint64_t duration) { mxverb(2, "delivering audio for %u/'%s' length %llu timecode %llu flags " "0x%08x duration %llu\n", dmx->track->id, ti->fname, segment.size, dmx->c_timecode, (uint32_t)segment.offset, duration); - dmx->packetizer->process(segment.data, segment.size, - dmx->c_timecode, duration, + memory_c mem(segment.data, segment.size, true); + dmx->packetizer->process(mem, dmx->c_timecode, duration, (segment.offset & 2) == 2 ? -1 : dmx->c_reftimecode); if ((segment.offset & 2) == 2) @@ -563,14 +557,16 @@ real_reader_c::deliver_audio_frames(real_demuxer_t *dmx, uint64_t duration) { void real_reader_c::deliver_aac_frames(real_demuxer_t *dmx, - unsigned char *chunk, - uint32_t length) { + memory_c &mem) { uint32_t num_sub_packets, data_idx, i, sub_length, len_check; + uint32_t length; + unsigned char *chunk; + chunk = mem.data; + length = mem.size; if (length < 2) { mxwarn(PFX "Short AAC audio packet for track ID %u of " "'%s' (length: %u < 2)\n", dmx->track->id, ti->fname, length); - safefree(chunk); return; } num_sub_packets = chunk[1] >> 4; @@ -579,7 +575,6 @@ real_reader_c::deliver_aac_frames(real_demuxer_t *dmx, mxwarn(PFX "Short AAC audio packet for track ID %u of " "'%s' (length: %u < %u)\n", dmx->track->id, ti->fname, length, 2 + num_sub_packets * 2); - safefree(chunk); return; } len_check = 2 + num_sub_packets * 2; @@ -592,16 +587,15 @@ real_reader_c::deliver_aac_frames(real_demuxer_t *dmx, mxwarn(PFX "Inconsistent AAC audio packet for track ID %u of " "'%s' (length: %u != len_check %u)\n", dmx->track->id, ti->fname, length, len_check); - safefree(chunk); return; } data_idx = 2 + num_sub_packets * 2; for (i = 0; i < num_sub_packets; i++) { sub_length = get_uint16_be(&chunk[2 + i * 2]); - dmx->packetizer->process(&chunk[data_idx], sub_length); + memory_c mem(&chunk[data_idx], sub_length, false); + dmx->packetizer->process(mem); data_idx += sub_length; } - safefree(chunk); } // }}} @@ -735,7 +729,8 @@ real_reader_c::deliver_segments(real_demuxer_t *dmx, ptr += segment->size; } - dmx->packetizer->process(buffer, len, timecode, -1, + memory_c mem(buffer, len, true); + dmx->packetizer->process(mem, timecode, -1, dmx->c_keyframe ? VFT_IFRAME : VFT_PFRAMEAUTOMATIC); for (i = 0; i < dmx->segments->size(); i++) @@ -748,14 +743,13 @@ real_reader_c::deliver_segments(real_demuxer_t *dmx, // {{{ FUNCTSION real_reader_c::assemble_packet() void -real_reader_c::assemble_packet(real_demuxer_t *dmx, - unsigned char *p, - int size, - int64_t timecode, - bool keyframe) { +real_reader_c::assemble_video_packet(real_demuxer_t *dmx, + memory_c &mem, + int64_t timecode, + bool keyframe) { uint32_t vpkg_header, vpkg_length, vpkg_offset, vpkg_subseq, vpkg_seqnum; uint32_t len; - byte_cursor_c bc(p, size); + byte_cursor_c bc(mem.data, mem.size); rv_segment_t segment; int64_t this_timecode; diff --git a/src/input/r_real.h b/src/input/r_real.h index 5f01ccc02..f96467b65 100644 --- a/src/input/r_real.h +++ b/src/input/r_real.h @@ -90,8 +90,8 @@ protected: virtual void create_packetizers(); virtual void create_packetizer(int64_t tid); virtual real_demuxer_t *find_demuxer(int id); - virtual void assemble_packet(real_demuxer_t *dmx, unsigned char *p, int size, - int64_t timecode, bool keyframe); + virtual void assemble_video_packet(real_demuxer_t *dmx, memory_c &mem, + int64_t timecode, bool keyframe); virtual void deliver_segments(real_demuxer_t *dmx, int64_t timecode); virtual int finish(); virtual bool get_rv_dimensions(unsigned char *buf, int size, uint32_t &width, @@ -100,14 +100,11 @@ protected: int size); virtual void get_information_from_data(); virtual void flush_packetizers(); - virtual void deliver_aac_frames(real_demuxer_t *dmx, unsigned char *chunk, - uint32_t length); - virtual void queue_audio_frames(real_demuxer_t *dmx, unsigned char *chunk, - uint32_t length, uint64_t timecode, - uint32_t flags); - virtual void queue_one_audio_frame(real_demuxer_t *dmx, unsigned char *chunk, - uint32_t length, uint64_t timecode, - uint32_t flags); + virtual void deliver_aac_frames(real_demuxer_t *dmx, memory_c &mem); + virtual void queue_audio_frames(real_demuxer_t *dmx, memory_c &mem, + uint64_t timecode, uint32_t flags); + virtual void queue_one_audio_frame(real_demuxer_t *dmx, memory_c &mem, + uint64_t timecode, uint32_t flags); virtual void deliver_audio_frames(real_demuxer_t *dmx, uint64_t duration); }; diff --git a/src/input/r_srt.cpp b/src/input/r_srt.cpp index b2f026fb2..a0c28e533 100644 --- a/src/input/r_srt.cpp +++ b/src/input/r_srt.cpp @@ -92,6 +92,7 @@ srt_reader_c::srt_reader_c(track_info_c *nti) srt_reader_c::~srt_reader_c() { if (textsubs_packetizer != NULL) delete textsubs_packetizer; + delete mm_io; } #define STATE_INITIAL 0 diff --git a/src/input/r_ssa.cpp b/src/input/r_ssa.cpp index 9843dfe0d..9d549e87c 100644 --- a/src/input/r_ssa.cpp +++ b/src/input/r_ssa.cpp @@ -76,6 +76,7 @@ ssa_reader_c::ssa_reader_c(track_info_c *nti) is_ass = false; section = 0; + act_wchar = 0; try { mm_io = new mm_text_io_c(ti->fname); @@ -153,6 +154,7 @@ ssa_reader_c::ssa_reader_c(track_info_c *nti) ssa_reader_c::~ssa_reader_c() { if (textsubs_packetizer != NULL) delete textsubs_packetizer; + delete mm_io; } string @@ -292,8 +294,8 @@ ssa_reader_c::read(generic_packetizer_c *) { // Let the packetizer handle this line. mxprints(buffer, "%d", clines[i].num); line = string(buffer) + string(clines[i].line); - textsubs_packetizer->process((unsigned char *)line.c_str(), 0, - clines[i].start, + memory_c mem((unsigned char *)line.c_str(), 0, false); + textsubs_packetizer->process(mem, clines[i].start, clines[i].end - clines[i].start); safefree(clines[i].line); } diff --git a/src/input/r_vobsub.cpp b/src/input/r_vobsub.cpp index 46c724eee..6037ed67b 100644 --- a/src/input/r_vobsub.cpp +++ b/src/input/r_vobsub.cpp @@ -381,9 +381,8 @@ vobsub_reader_c::read(generic_packetizer_c *ptzr) { (uint32_t)(track->positions[i] & 0xffffffff), track->timecodes[i], ARG_TIMECODE_NS(track->timecodes[i]), track->durations[i]); - track->packetizer->process(data, track->sizes[i], track->timecodes[i], - track->durations[i]); - safefree(data); + memory_c mem(data, track->sizes[i], true); + track->packetizer->process(mem, track->timecodes[i], track->durations[i]); track->idx++; if (track->idx >= track->sizes.size()) { diff --git a/src/input/r_wav.cpp b/src/input/r_wav.cpp index aacda2b19..19a4f4021 100644 --- a/src/input/r_wav.cpp +++ b/src/input/r_wav.cpp @@ -184,7 +184,8 @@ wav_reader_c::read(generic_packetizer_c *) { return 0; } - pcmpacketizer->process(chunk, nread); + memory_c mem(chunk, nread, false); + pcmpacketizer->process(mem); bytes_processed += nread; @@ -221,7 +222,8 @@ wav_reader_c::read(generic_packetizer_c *) { erlen = words * 7 * sizeof(short); } - dtspacketizer->process((unsigned char *) (buf[cur_buf]), erlen); + memory_c mem((unsigned char *)buf[cur_buf], erlen, false); + dtspacketizer->process(mem); bytes_processed += rlen; diff --git a/src/input/subtitles.cpp b/src/input/subtitles.cpp index 198042e0e..3cb306c2d 100644 --- a/src/input/subtitles.cpp +++ b/src/input/subtitles.cpp @@ -133,9 +133,8 @@ void subtitles_c::process(textsubs_packetizer_c *p) { sub_t *current; while ((current = get_next()) != NULL) { - p->process((unsigned char *)current->subs, 0, current->start, - current->end - current->start); - safefree(current->subs); + memory_c mem((unsigned char *)current->subs, 0, true); + p->process(mem, current->start, current->end - current->start); safefree(current); } } diff --git a/src/mkvmerge.cpp b/src/mkvmerge.cpp index 7bace4021..ec876b976 100644 --- a/src/mkvmerge.cpp +++ b/src/mkvmerge.cpp @@ -2055,8 +2055,11 @@ parse_args(int argc, file->ti = ti; files.push_back(file); - } else + } else { + delete ti; + safefree(file->name); safefree(file); + } ti = new track_info_c; } @@ -2269,6 +2272,7 @@ cleanup() { while (files.size()) { file = files[files.size() - 1]; delete file->ti; + safefree(file->name); safefree(file); files.pop_back(); } diff --git a/src/output/p_aac.cpp b/src/output/p_aac.cpp index fa29260d1..4edf695d6 100644 --- a/src/output/p_aac.cpp +++ b/src/output/p_aac.cpp @@ -53,7 +53,6 @@ aac_packetizer_c::aac_packetizer_c(generic_reader_c *nreader, set_track_type(track_audio); set_track_default_duration((int64_t)(1024 * 1000000000.0 * ti->async.linear / samples_per_sec)); - duplicate_data_on_add(headerless); } aac_packetizer_c::~aac_packetizer_c() { @@ -129,7 +128,8 @@ aac_packetizer_c::get_aac_packet(unsigned long *header, return buf; } -void aac_packetizer_c::set_headers() { +void +aac_packetizer_c::set_headers() { if (id == AAC_ID_MPEG4) { if (profile == AAC_PROFILE_MAIN) set_codec_id(MKV_A_AAC_4MAIN); @@ -162,8 +162,7 @@ void aac_packetizer_c::set_headers() { } int -aac_packetizer_c::process(unsigned char *buf, - int size, +aac_packetizer_c::process(memory_c &mem, int64_t timecode, int64_t, int64_t, @@ -191,20 +190,20 @@ aac_packetizer_c::process(unsigned char *buf, return EMOREDATA; } while (needs_positive_displacement(duration)) { - add_packet(buf, size, my_timecode + ti->async.displacement, duration); + add_packet(mem, my_timecode + ti->async.displacement, duration); displace(duration); } my_timecode = (int64_t)((my_timecode + ti->async.displacement) * ti->async.linear); - add_packet(buf, size, my_timecode, duration); + add_packet(mem, my_timecode, duration); debug_leave("aac_packetizer_c::process"); return EMOREDATA; } - byte_buffer.add(buf, size); + byte_buffer.add(mem.data, mem.size); while ((packet = get_aac_packet(&header, &aacheader)) != NULL) { if (timecode == -1) my_timecode = (int64_t)(1024 * 1000000000.0 * packetno / @@ -212,7 +211,8 @@ aac_packetizer_c::process(unsigned char *buf, else my_timecode = timecode + ti->async.displacement; my_timecode = (int64_t)(my_timecode * ti->async.linear); - add_packet(packet, aacheader.data_byte_size, my_timecode, + memory_c mem(packet, aacheader.data_byte_size, true); + add_packet(mem, my_timecode, (int64_t)(1024 * 1000000000.0 * ti->async.linear / samples_per_sec)); packetno++; diff --git a/src/output/p_aac.h b/src/output/p_aac.h index b7f650bac..234a47dd1 100644 --- a/src/output/p_aac.h +++ b/src/output/p_aac.h @@ -52,7 +52,7 @@ public: bool nheaderless = false) throw (error_c); virtual ~aac_packetizer_c(); - virtual int process(unsigned char *buf, int size, int64_t timecode = -1, + virtual int process(memory_c &mem, int64_t timecode = -1, int64_t length = -1, int64_t bref = -1, int64_t fref = -1); virtual void set_headers(); diff --git a/src/output/p_ac3.cpp b/src/output/p_ac3.cpp index 7e646a419..b0942416d 100644 --- a/src/output/p_ac3.cpp +++ b/src/output/p_ac3.cpp @@ -48,7 +48,6 @@ ac3_packetizer_c::ac3_packetizer_c(generic_reader_c *nreader, if (use_durations) set_track_default_duration((int64_t)(1536000000000.0 *ti->async.linear / samples_per_sec)); - duplicate_data_on_add(false); } ac3_packetizer_c::~ac3_packetizer_c() { @@ -130,8 +129,7 @@ ac3_packetizer_c::set_headers() { } int -ac3_packetizer_c::process(unsigned char *buf, - int size, +ac3_packetizer_c::process(memory_c &mem, int64_t timecode, int64_t, int64_t, @@ -143,7 +141,7 @@ ac3_packetizer_c::process(unsigned char *buf, debug_enter("ac3_packetizer_c::process"); - add_to_buffer(buf, size); + add_to_buffer(mem.data, mem.size); while ((packet = get_ac3_packet(&header, &ac3header)) != NULL) { if (timecode == -1) my_timecode = (int64_t)(1000000000.0 * packetno * 1536 / @@ -151,7 +149,8 @@ ac3_packetizer_c::process(unsigned char *buf, else my_timecode = timecode + ti->async.displacement; my_timecode = (int64_t)(my_timecode * ti->async.linear); - add_packet(packet, ac3header.bytes, my_timecode, + memory_c mem(packet, ac3header.bytes, true); + add_packet(mem, my_timecode, (int64_t)(1000000000.0 * 1536 * ti->async.linear / samples_per_sec)); packetno++; diff --git a/src/output/p_ac3.h b/src/output/p_ac3.h index 03b320041..8e9a47bef 100644 --- a/src/output/p_ac3.h +++ b/src/output/p_ac3.h @@ -41,7 +41,7 @@ public: throw (error_c); virtual ~ac3_packetizer_c(); - virtual int process(unsigned char *buf, int size, int64_t timecode = -1, + virtual int process(memory_c &mem, int64_t timecode = -1, int64_t length = -1, int64_t bref = -1, int64_t fref = -1); virtual void set_headers(); diff --git a/src/output/p_dts.cpp b/src/output/p_dts.cpp index cb603c8cf..73292190b 100644 --- a/src/output/p_dts.cpp +++ b/src/output/p_dts.cpp @@ -102,7 +102,6 @@ dts_packetizer_c::dts_packetizer_c(generic_reader_c *nreader, last_header = dtsheader; set_track_type(track_audio); - duplicate_data_on_add(false); } dts_packetizer_c::~dts_packetizer_c() { @@ -222,8 +221,7 @@ dts_packetizer_c::set_headers() { } int -dts_packetizer_c::process(unsigned char *buf, - int size, +dts_packetizer_c::process(memory_c &mem, int64_t timecode, int64_t, int64_t, @@ -236,7 +234,7 @@ dts_packetizer_c::process(unsigned char *buf, if (timecode != -1) my_timecode = timecode; - add_to_buffer(buf, size); + add_to_buffer(mem.data, mem.size); dts_header_t dtsheader; unsigned char *packet; @@ -250,8 +248,9 @@ dts_packetizer_c::process(unsigned char *buf, else my_timecode = timecode + ti->async.displacement; my_timecode = (int64_t)(my_timecode * ti->async.linear); - add_packet(packet, dtsheader.frame_byte_size, my_timecode, - (int64_t)(packet_len_in_ns * ti->async.linear)); + memory_c mem(packet, dtsheader.frame_byte_size, true); + add_packet(mem, my_timecode, (int64_t)(packet_len_in_ns * + ti->async.linear)); bytes_written += dtsheader.frame_byte_size; samples_written += get_dts_packet_length_in_core_samples(&dtsheader); diff --git a/src/output/p_dts.h b/src/output/p_dts.h index ae5fe44e9..b59cad1da 100644 --- a/src/output/p_dts.h +++ b/src/output/p_dts.h @@ -45,7 +45,7 @@ public: track_info_c *nti) throw (error_c); virtual ~dts_packetizer_c(); - virtual int process(unsigned char *buf, int size, int64_t timecode = -1, + virtual int process(memory_c &mem, int64_t timecode = -1, int64_t length = -1, int64_t bref = -1, int64_t fref = -1); virtual void set_headers(); diff --git a/src/output/p_flac.cpp b/src/output/p_flac.cpp index d1163e936..516cd5b19 100644 --- a/src/output/p_flac.cpp +++ b/src/output/p_flac.cpp @@ -86,8 +86,7 @@ flac_packetizer_c::set_headers() { } int -flac_packetizer_c::process(unsigned char *data, - int size, +flac_packetizer_c::process(memory_c &mem, int64_t timecode, int64_t, int64_t, @@ -96,7 +95,7 @@ flac_packetizer_c::process(unsigned char *data, if (timecode == -1) timecode = last_timecode; last_timecode = timecode; - add_packet(data, size, timecode, 0); + add_packet(mem, timecode, 0); debug_leave("flac_packetizer_c::process"); return EMOREDATA; diff --git a/src/output/p_flac.h b/src/output/p_flac.h index 7c09e94f0..ed304a4ea 100644 --- a/src/output/p_flac.h +++ b/src/output/p_flac.h @@ -43,7 +43,7 @@ public: track_info_c *nti) throw (error_c); virtual ~flac_packetizer_c(); - virtual int process(unsigned char *data, int size, int64_t timecode = -1, + virtual int process(memory_c &mem, int64_t timecode = -1, int64_t length = -1, int64_t bref = -1, int64_t fref = -1); virtual void set_headers(); diff --git a/src/output/p_mp3.cpp b/src/output/p_mp3.cpp index e24516ae8..cebd812e1 100644 --- a/src/output/p_mp3.cpp +++ b/src/output/p_mp3.cpp @@ -47,7 +47,6 @@ mp3_packetizer_c::mp3_packetizer_c(generic_reader_c *nreader, set_track_type(track_audio); set_track_default_duration((int64_t)(1152000000000.0 * ti->async.linear / samples_per_sec)); - duplicate_data_on_add(false); } mp3_packetizer_c::~mp3_packetizer_c() { @@ -148,8 +147,7 @@ mp3_packetizer_c::set_headers() { } int -mp3_packetizer_c::process(unsigned char *buf, - int size, +mp3_packetizer_c::process(memory_c &mem, int64_t timecode, int64_t, int64_t, @@ -160,7 +158,7 @@ mp3_packetizer_c::process(unsigned char *buf, debug_enter("mp3_packetizer_c::process"); - byte_buffer.add(buf, size); + byte_buffer.add(mem.data, mem.size); while ((packet = get_mp3_packet(&mp3header)) != NULL) { #ifdef DEBUG dump_packet(packet, mp3header.framesize); @@ -171,7 +169,8 @@ mp3_packetizer_c::process(unsigned char *buf, else my_timecode = timecode + ti->async.displacement; my_timecode = (int64_t)(my_timecode * ti->async.linear); - add_packet(packet, mp3header.framesize, my_timecode, + memory_c mem(packet, mp3header.framesize, true); + add_packet(mem, my_timecode, (int64_t)(1000000000.0 * spf * ti->async.linear / samples_per_sec)); packetno++; diff --git a/src/output/p_mp3.h b/src/output/p_mp3.h index 1f01bbf8d..dd335de2a 100644 --- a/src/output/p_mp3.h +++ b/src/output/p_mp3.h @@ -42,7 +42,7 @@ public: throw (error_c); virtual ~mp3_packetizer_c(); - virtual int process(unsigned char *buf, int size, int64_t timecode = -1, + virtual int process(memory_c &mem, int64_t timecode = -1, int64_t length = -1, int64_t bref = -1, int64_t fref = -1); virtual void set_headers(); diff --git a/src/output/p_passthrough.cpp b/src/output/p_passthrough.cpp index 89cc02183..044cededc 100644 --- a/src/output/p_passthrough.cpp +++ b/src/output/p_passthrough.cpp @@ -37,6 +37,7 @@ passthrough_packetizer_c::passthrough_packetizer_c(generic_reader_c *nreader, generic_packetizer_c(nreader, nti) { packets_processed = 0; bytes_processed = 0; + sync_to_keyframe = false; } void @@ -45,18 +46,16 @@ passthrough_packetizer_c::set_headers() { } int -passthrough_packetizer_c::process(unsigned char *buf, - int size, +passthrough_packetizer_c::process(memory_c &mem, int64_t timecode, int64_t duration, int64_t bref, int64_t fref) { - return process(buf, size, timecode, duration, bref, fref, false); + return process(mem, timecode, duration, bref, fref, false); } int -passthrough_packetizer_c::process(unsigned char *buf, - int size, +passthrough_packetizer_c::process(memory_c &mem, int64_t timecode, int64_t duration, int64_t bref, @@ -65,7 +64,7 @@ passthrough_packetizer_c::process(unsigned char *buf, debug_enter("passthrough_packetizer_c::process"); packets_processed++; - bytes_processed += size; + bytes_processed += mem.size; if ((duration > 0) && needs_negative_displacement(duration)) { displace(-duration); sync_to_keyframe = true; @@ -76,18 +75,15 @@ passthrough_packetizer_c::process(unsigned char *buf, // Not implemented yet. } while ((duration > 0) && needs_positive_displacement(duration)) { - add_packet(buf, size, + add_packet(mem, (int64_t)((timecode + ti->async.displacement) * ti->async.linear), - duration, duration_mandatory, bref, fref, -1, cp_yes); + duration, duration_mandatory, bref, fref); displace(duration); } - if (sync_to_keyframe && (bref != -1)) { - if (!duplicate_data) - safefree(buf); + if (sync_to_keyframe && (bref != -1)) return EMOREDATA; - } sync_to_keyframe = false; timecode = (int64_t)((timecode + ti->async.displacement) * ti->async.linear); duration = (int64_t)(duration * ti->async.linear); @@ -95,7 +91,7 @@ passthrough_packetizer_c::process(unsigned char *buf, bref = (int64_t)((bref + ti->async.displacement) * ti->async.linear); if (fref >= 0) fref = (int64_t)((fref + ti->async.displacement) * ti->async.linear); - add_packet(buf, size, timecode, duration, duration_mandatory, bref, fref); + add_packet(mem, timecode, duration, duration_mandatory, bref, fref); debug_leave("passthrough_packetizer_c::process"); return EMOREDATA; diff --git a/src/output/p_passthrough.h b/src/output/p_passthrough.h index bf6a70e77..11d7b0049 100644 --- a/src/output/p_passthrough.h +++ b/src/output/p_passthrough.h @@ -35,10 +35,10 @@ public: passthrough_packetizer_c(generic_reader_c *nreader, track_info_c *nti) throw (error_c); - virtual int process(unsigned char *buf, int size, int64_t timecode = -1, + virtual int process(memory_c &mem, int64_t timecode = -1, int64_t duration = -1, int64_t bref = -1, int64_t fref = -1); - virtual int process(unsigned char *buf, int size, int64_t timecode, + virtual int process(memory_c &mem, int64_t timecode, int64_t duration, int64_t bref, int64_t fref, bool duration_mandatory); virtual void set_headers(); diff --git a/src/output/p_pcm.cpp b/src/output/p_pcm.cpp index d0b00437b..1e4de1dd4 100644 --- a/src/output/p_pcm.cpp +++ b/src/output/p_pcm.cpp @@ -80,8 +80,7 @@ pcm_packetizer_c::set_headers() { } int -pcm_packetizer_c::process(unsigned char *buf, - int size, +pcm_packetizer_c::process(memory_c &mem, int64_t, int64_t, int64_t, @@ -107,24 +106,22 @@ pcm_packetizer_c::process(unsigned char *buf, } if (skip_bytes) { - if (skip_bytes > size) { - skip_bytes -= size; + if (skip_bytes > mem.size) { + skip_bytes -= mem.size; return EMOREDATA; } - size -= skip_bytes; - new_buf = &buf[skip_bytes]; + mem.size -= skip_bytes; + new_buf = &mem.data[skip_bytes]; skip_bytes = 0; } else - new_buf = buf; + new_buf = mem.data; - buffer.add(new_buf, size); - if (!duplicate_data) - safefree(buf); + buffer.add(new_buf, mem.size); while (buffer.get_size() >= packet_size) { - add_packet(buffer.get_buffer(), packet_size, bytes_output * 1000000000 / - bps, packet_size * 1000000000 / bps, false, -1, -1, -1, - cp_yes); + memory_c mem(buffer.get_buffer(), packet_size, false); + add_packet(mem, bytes_output * 1000000000 / bps, packet_size * 1000000000 / + bps); buffer.remove(packet_size); bytes_output += packet_size; } @@ -140,8 +137,9 @@ pcm_packetizer_c::flush() { size = buffer.get_size(); if (size > 0) { - add_packet(buffer.get_buffer(), size, bytes_output * 1000000000 / - bps, size * 1000000000 / bps, false, -1, -1, -1, cp_yes); + memory_c mem(buffer.get_buffer(), size, false); + add_packet(mem, bytes_output * 1000000000 / bps, + size * 1000000000 / bps); bytes_output += size; buffer.remove(size); } diff --git a/src/output/p_pcm.h b/src/output/p_pcm.h index 0295a040f..893c3a091 100644 --- a/src/output/p_pcm.h +++ b/src/output/p_pcm.h @@ -42,7 +42,7 @@ public: throw (error_c); virtual ~pcm_packetizer_c(); - virtual int process(unsigned char *buf, int size, int64_t timecode = -1, + virtual int process(memory_c &mem, int64_t timecode = -1, int64_t length = -1, int64_t bref = -1, int64_t fref = -1); virtual void set_headers(); diff --git a/src/output/p_textsubs.cpp b/src/output/p_textsubs.cpp index d31b71e2a..7e46f0aaa 100644 --- a/src/output/p_textsubs.cpp +++ b/src/output/p_textsubs.cpp @@ -72,8 +72,7 @@ textsubs_packetizer_c::set_headers() { } int -textsubs_packetizer_c::process(unsigned char *_subs, - int, +textsubs_packetizer_c::process(memory_c &mem, int64_t start, int64_t length, int64_t, @@ -101,7 +100,7 @@ textsubs_packetizer_c::process(unsigned char *_subs, } // Count the number of lines. - idx1 = (char *)_subs; + idx1 = (char *)mem.data; subs = NULL; num_newlines = 0; while (*idx1 != 0) { @@ -109,10 +108,10 @@ textsubs_packetizer_c::process(unsigned char *_subs, num_newlines++; idx1++; } - subs = (char *)safemalloc(strlen((char *)_subs) + num_newlines * 2 + 1); + subs = (char *)safemalloc(strlen((char *)mem.data) + num_newlines * 2 + 1); // Unify the new lines into DOS style newlines. - idx1 = (char *)_subs; + idx1 = (char *)mem.data; idx2 = subs; while (*idx1 != 0) { if (*idx1 == '\n') { @@ -136,13 +135,13 @@ textsubs_packetizer_c::process(unsigned char *_subs, if (recode) { utf8_subs = to_utf8(cc_utf8, subs); - add_packet((unsigned char *)utf8_subs, strlen(utf8_subs), start, length, - true); - safefree(utf8_subs); - } else - add_packet((unsigned char *)subs, strlen(subs), start, length, true); - - safefree(subs); + safefree(subs); + memory_c mem((unsigned char *)utf8_subs, strlen(utf8_subs), true); + add_packet(mem, start, length, true); + } else { + memory_c mem((unsigned char *)subs, strlen(subs), true); + add_packet(mem, start, length, true); + } return EMOREDATA; } diff --git a/src/output/p_textsubs.h b/src/output/p_textsubs.h index 387acf886..abda204ca 100644 --- a/src/output/p_textsubs.h +++ b/src/output/p_textsubs.h @@ -42,7 +42,7 @@ public: throw (error_c); virtual ~textsubs_packetizer_c(); - virtual int process(unsigned char *_subs, int size, int64_t start = -1, + virtual int process(memory_c &mem, int64_t start = -1, int64_t length = -1, int64_t bref = -1, int64_t fref = -1); virtual void set_headers(); diff --git a/src/output/p_video.cpp b/src/output/p_video.cpp index 000b96ccb..4db8aca3f 100644 --- a/src/output/p_video.cpp +++ b/src/output/p_video.cpp @@ -126,8 +126,7 @@ video_packetizer_c::set_headers() { // fref > 0: B frame with given forward reference (absolute reference, // not relative!) int -video_packetizer_c::process(unsigned char *buf, - int size, +video_packetizer_c::process(memory_c &mem, int64_t old_timecode, int64_t duration, int64_t bref, @@ -139,7 +138,7 @@ video_packetizer_c::process(unsigned char *buf, debug_enter("video_packetizer_c::process"); if (hack_engaged(ENGAGE_NATIVE_BFRAMES) && is_mpeg4 && (fps != 0.0)) { - find_mpeg4_frame_types(buf, size, frames); + find_mpeg4_frame_types(mem.data, mem.size, frames); for (i = 0; i < frames.size(); i++) { if ((frames[i].type == 'I') || ((frames[i].type != 'B') && (fref_frame.type != '?'))) @@ -159,7 +158,7 @@ video_packetizer_c::process(unsigned char *buf, frames_output++; frames[i].timecode = timecode; frames[i].duration = duration; - frames[i].data = (unsigned char *)safememdup(&buf[frames[i].pos], + frames[i].data = (unsigned char *)safememdup(&mem.data[frames[i].pos], frames[i].size); if (frames[i].type == 'I') { @@ -167,8 +166,8 @@ video_packetizer_c::process(unsigned char *buf, frames[i].fref = -1; if (bref_frame.type == '?') { bref_frame = frames[i]; - add_packet(frames[i].data, frames[i].size, frames[i].timecode, - frames[i].duration, false, -1, -1, -1, cp_no); + memory_c mem(frames[i].data, frames[i].size, false); + add_packet(mem, frames[i].timecode, frames[i].duration); } else fref_frame = frames[i]; @@ -196,9 +195,6 @@ video_packetizer_c::process(unsigned char *buf, debug_leave("video_packetizer_c::process"); - if (!duplicate_data) - safefree(buf); - return EMOREDATA; } @@ -215,12 +211,12 @@ video_packetizer_c::process(unsigned char *buf, if (bref == VFT_IFRAME) { // Add a key frame and save its timecode so that we can reference it later. - add_packet(buf, size, timecode, duration); + add_packet(mem, timecode, duration); ref_timecode = timecode; } else { // P or B frame. Use our last timecode if the bref is -2, or the provided // one otherwise. The forward ref is always taken from the reader. - add_packet(buf, size, timecode, duration, false, + add_packet(mem, timecode, duration, false, bref == VFT_PFRAMEAUTOMATIC ? ref_timecode : bref, fref); if (fref == VFT_NOBFRAME) ref_timecode = timecode; @@ -335,8 +331,9 @@ video_packetizer_c::flush_frames(char next_frame, queued_frames.clear(); } if (flush_all) { - add_packet(bref_frame.data, bref_frame.size, bref_frame.duration, - false, bref_frame.bref, bref_frame.fref, -1, cp_no); + memory_c mem(bref_frame.data, bref_frame.size, false); + add_packet(mem, bref_frame.duration, false, bref_frame.bref, + bref_frame.fref); bref_frame.type = '?'; } return; @@ -347,15 +344,15 @@ video_packetizer_c::flush_frames(char next_frame, frames_output++; fref_frame.timecode = (int64_t)(fref_frame.timecode + queued_frames.size() * 1000000000 / fps); - add_packet(fref_frame.data, fref_frame.size, fref_frame.timecode, - fref_frame.duration, false, fref_frame.bref, fref_frame.fref, - -1, cp_no); + memory_c fref_mem(fref_frame.data, fref_frame.size, false); + add_packet(fref_mem, fref_frame.timecode, + fref_frame.duration, false, fref_frame.bref, fref_frame.fref); - for (i = 0; i < queued_frames.size(); i++) - add_packet(queued_frames[i].data, queued_frames[i].size, - queued_frames[i].timecode, queued_frames[i].duration, - false, bref_frame.timecode, fref_frame.timecode, -1, - cp_no); + for (i = 0; i < queued_frames.size(); i++) { + memory_c mem(queued_frames[i].data, queued_frames[i].size, false); + add_packet(mem, queued_frames[i].timecode, queued_frames[i].duration, + false, bref_frame.timecode, fref_frame.timecode); + } queued_frames.clear(); bref_frame = fref_frame; diff --git a/src/output/p_video.h b/src/output/p_video.h index f4d912792..e37ed49ff 100644 --- a/src/output/p_video.h +++ b/src/output/p_video.h @@ -54,7 +54,7 @@ public: throw (error_c); virtual ~video_packetizer_c(); - virtual int process(unsigned char *buf, int size, int64_t old_timecode = -1, + virtual int process(memory_c &mem, int64_t old_timecode = -1, int64_t duration = -1, int64_t bref = VFT_IFRAME, int64_t fref = VFT_NOBFRAME); virtual void set_headers(); diff --git a/src/output/p_vobsub.cpp b/src/output/p_vobsub.cpp index bd38af588..1bd9eef06 100644 --- a/src/output/p_vobsub.cpp +++ b/src/output/p_vobsub.cpp @@ -176,17 +176,17 @@ vobsub_packetizer_c::deliver_packet(unsigned char *buf, } if (duration != -2) { timecode = (int64_t)((float)timecode * ti->async.linear); - add_packet(buf, size, timecode, duration, true); - } - safefree(buf); + memory_c mem(buf, size, true); + add_packet(mem, timecode, duration, true); + } else + safefree(buf); return -1; } // Adopted from mplayer's vobsub.c int -vobsub_packetizer_c::process(unsigned char *srcbuf, - int size, +vobsub_packetizer_c::process(memory_c &mem, int64_t timecode, int64_t duration, int64_t, @@ -207,7 +207,7 @@ vobsub_packetizer_c::process(unsigned char *srcbuf, return EMOREDATA; if (extract_from_mpeg) { - mm_mem_io_c in(srcbuf, size); + mm_mem_io_c in(mem.data, mem.size); dst_buf = NULL; dst_size = 0; @@ -337,7 +337,7 @@ vobsub_packetizer_c::process(unsigned char *srcbuf, } dst_size += packet_size; spu_size += packet_size; - overhead += size - packet_size; + overhead += mem.size - packet_size; idx = len; } @@ -371,9 +371,9 @@ vobsub_packetizer_c::process(unsigned char *srcbuf, return deliver(); } - spu_size += size; + spu_size += mem.size; timecode = (int64_t)((float)timecode * ti->async.linear); - add_packet(srcbuf, size, timecode, duration, true); + add_packet(mem, timecode, duration, true); return EMOREDATA; } diff --git a/src/output/p_vobsub.h b/src/output/p_vobsub.h index bcf20519f..e394ac687 100644 --- a/src/output/p_vobsub.h +++ b/src/output/p_vobsub.h @@ -41,7 +41,7 @@ public: throw (error_c); virtual ~vobsub_packetizer_c(); - virtual int process(unsigned char *srcbuf, int size, + virtual int process(memory_c &mem, int64_t old_timecode = -1, int64_t duration = -1, int64_t bref = -1, int64_t fref = -1); virtual void set_headers(); diff --git a/src/output/p_vorbis.cpp b/src/output/p_vorbis.cpp index e868c0fc4..9d6830009 100644 --- a/src/output/p_vorbis.cpp +++ b/src/output/p_vorbis.cpp @@ -83,6 +83,8 @@ vorbis_packetizer_c::~vorbis_packetizer_c() { for (i = 0; i < 3; i++) if (headers[i].packet != NULL) safefree(headers[i].packet); + vorbis_info_clear(&vi); + vorbis_comment_clear(&vc); } void @@ -140,8 +142,7 @@ vorbis_packetizer_c::set_headers() { * has to generate silence packets and put them into the Matroska file first. */ int -vorbis_packetizer_c::process(unsigned char *data, - int size, +vorbis_packetizer_c::process(memory_c &mem, int64_t timecode, int64_t, int64_t, @@ -170,7 +171,8 @@ vorbis_packetizer_c::process(unsigned char *data, samples += samples_here; last_bs = this_bs; samples_here = (this_bs + last_bs) / 4; - add_packet(zero, 2, samples * 1000 / vi.rate, + memory_c mem(zero, 2, false); + add_packet(mem, samples * 1000 / vi.rate, samples_here * 1000000000 / vi.rate); } } @@ -189,8 +191,8 @@ vorbis_packetizer_c::process(unsigned char *data, // Update the number of samples we have processed so that we can // calculate the timecode on the next call. - op.packet = data; - op.bytes = size; + op.packet = mem.data; + op.bytes = mem.size; this_bs = vorbis_packet_blocksize(&vi, &op); samples_here = (this_bs + last_bs) / 4; samples += samples_here; @@ -203,7 +205,7 @@ vorbis_packetizer_c::process(unsigned char *data, } mxverb(2, "Vorbis: samples_here: %lld\n", samples_here); - add_packet(data, size, (int64_t)timecode, + add_packet(mem, (int64_t)timecode, (int64_t)(samples_here * 1000000000 * ti->async.linear / vi.rate)); diff --git a/src/output/p_vorbis.h b/src/output/p_vorbis.h index 410901912..b107c4d42 100644 --- a/src/output/p_vorbis.h +++ b/src/output/p_vorbis.h @@ -47,7 +47,7 @@ public: track_info_c *nti) throw (error_c); virtual ~vorbis_packetizer_c(); - virtual int process(unsigned char *data, int size, int64_t timecode = -1, + virtual int process(memory_c &mem, int64_t timecode = -1, int64_t length = -1, int64_t bref = -1, int64_t fref = -1); virtual void set_headers(); diff --git a/src/pr_generic.cpp b/src/pr_generic.cpp index f0396c8d8..af1759c86 100644 --- a/src/pr_generic.cpp +++ b/src/pr_generic.cpp @@ -54,7 +54,6 @@ generic_packetizer_c::generic_packetizer_c(generic_reader_c *nreader, #endif reader = nreader; add_packetizer(this); - duplicate_data = true; track_entry = NULL; ti = new track_info_c(*nti); @@ -659,23 +658,21 @@ void generic_packetizer_c::set_headers() { } void -generic_packetizer_c::add_packet(unsigned char *data, - int length, +generic_packetizer_c::add_packet(memory_c &mem, int64_t timecode, int64_t duration, bool duration_mandatory, int64_t bref, int64_t fref, - int ref_priority, - copy_packet_mode_t copy_this) { + int ref_priority) { + int length; packet_t *pack; - if (data == NULL) - return; if (timecode < 0) { - drop_packet(data, copy_this); + mem.release(); return; } + // 'timecode < safety_last_timecode' may only occur for B frames. In this // case we have the coding order, e.g. IPB1B2 and the timecodes // I: 0, P: 120, B1: 40, B2: 80. @@ -688,16 +685,16 @@ generic_packetizer_c::add_packet(unsigned char *data, pack = (packet_t *)safemalloc(sizeof(packet_t)); memset(pack, 0, sizeof(packet_t)); + length = mem.size; if (compressor != NULL) { - pack->data = compressor->compress(data, length); - if ((copy_this == cp_no) || - ((copy_this == cp_default) && !duplicate_data)) - safefree(data); - } else if ((copy_this == cp_yes) || - ((copy_this == cp_default) && duplicate_data)) - pack->data = (unsigned char *)safememdup(data, length); - else - pack->data = data; + pack->data = compressor->compress(mem.data, length); + mem.release(); + } else if (!mem.is_free) + pack->data = (unsigned char *)safememdup(mem.data, mem.size); + else { + pack->data = mem.data; + mem.lock(); + } pack->length = length; pack->timecode = timecode; pack->bref = bref; @@ -713,13 +710,6 @@ generic_packetizer_c::add_packet(unsigned char *data, enqueued_bytes += pack->length; } -void generic_packetizer_c::drop_packet(unsigned char *data, - copy_packet_mode_t copy_this) { - if ((copy_this == cp_no) || - ((copy_this == cp_default) && !duplicate_data)) - safefree(data); -} - packet_t *generic_packetizer_c::get_packet() { packet_t *pack; diff --git a/src/pr_generic.h b/src/pr_generic.h index 7dc125f64..ff72865ef 100644 --- a/src/pr_generic.h +++ b/src/pr_generic.h @@ -53,18 +53,53 @@ using namespace std; #define CUES_ALL 2 #define CUES_SPARSE 3 +class memory_c { +public: + unsigned char *data; + uint32_t size; + bool is_free; + +public: + memory_c(unsigned char *ndata, uint32_t nsize, bool nis_free): + data(ndata), size(nsize), is_free(nis_free) { + if (data == NULL) + die("memory_c::memory_c: data = %p, size = %u\n", data, size); + } + memory_c(const memory_c &src) { + die("memory_c::memory_c(const memory_c &) called\n"); + } + ~memory_c() { + release(); + } + int lock() { + is_free = false; + return 0; + } + memory_c *grab() { + if (size == 0) + die("memory_c::grab(): size == 0\n"); + if (is_free) { + is_free = false; + return new memory_c(data, size, true); + } + return new memory_c((unsigned char *)safememdup(data, size), size, true); + } + int release() { + if (is_free) { + safefree(data); + data = NULL; + is_free = false; + } + return 0; + } +}; + typedef struct { int64_t displacement; double linear; int64_t id; } audio_sync_t; -enum copy_packet_mode_t { - cp_default, - cp_yes, - cp_no -}; - #define DEFAULT_TRACK_PRIOIRTY_NONE 0 #define DEFAULT_TRACK_PRIORITY_FROM_TYPE 10 #define DEFAULT_TRACK_PRIORITY_FROM_SOURCE 50 @@ -218,7 +253,6 @@ class generic_packetizer_c { protected: deque packet_queue; generic_reader_c *reader; - bool duplicate_data; track_info_c *ti; int64_t initial_displacement; @@ -268,15 +302,10 @@ public: track_entry = NULL; } - virtual void duplicate_data_on_add(bool duplicate) { - duplicate_data = duplicate; - } - virtual void add_packet(unsigned char *data, int lenth, int64_t timecode, + virtual void add_packet(memory_c &mem, int64_t timecode, int64_t duration, bool duration_mandatory = false, int64_t bref = -1, int64_t fref = -1, - int ref_priority = -1, - copy_packet_mode_t copy_this = cp_default); - virtual void drop_packet(unsigned char *data, copy_packet_mode_t copy_this); + int ref_priority = -1); virtual packet_t *get_packet(); virtual int packet_available() { return packet_queue.size(); @@ -298,7 +327,7 @@ public: return free_refs; } virtual void set_headers(); - virtual int process(unsigned char *data, int size, + virtual int process(memory_c &mem, int64_t timecode = -1, int64_t length = -1, int64_t bref = -1, int64_t fref = -1) = 0;