-static int flushbuf(hb_stream_t *stream)
-{
- int old_write_index = stream->ps_current_write_buffer_index;
-
- // Flip the buffers and start moving on to the next
- stream->ps_current_write_buffer_index++;
- if (stream->ps_current_write_buffer_index > kNumDecodeBuffers-1)
- stream->ps_current_write_buffer_index = 0;
-
- if ( (stream->ps_decode_buffer[stream->ps_current_write_buffer_index].len != 0) || (stream->ps_decode_buffer[stream->ps_current_write_buffer_index].write_pos != 0) )
- {
- hb_log("flushbuf - new buffer (index %d) has non zero length and write position !", stream->ps_current_write_buffer_index);
- return 0;
- }
-
- stream->ps_current_read_buffer_index = old_write_index;
- stream->ps_decode_buffer[stream->ps_current_read_buffer_index].read_pos = 0;
-
- return 1;
-}
-
-static int fwrite64(void* buf, int elsize, int elnum, hb_stream_t* stream)
-{
- int size = elsize;
- if (elnum > 1)
- size *= elnum;
-
- int written = 0;
- int current_write_index = stream->ps_current_write_buffer_index;
-
- if (size <= stream->ps_decode_buffer[current_write_index].size - stream->ps_decode_buffer[current_write_index].write_pos)
- {
- memcpy(stream->ps_decode_buffer[current_write_index].data + stream->ps_decode_buffer[current_write_index].write_pos, buf, size);
- stream->ps_decode_buffer[current_write_index].write_pos += size;
- stream->ps_decode_buffer[current_write_index].len = stream->ps_decode_buffer[current_write_index].write_pos;
- written = size;
- }
- else
- {
- memcpy(stream->ps_decode_buffer[current_write_index].data + stream->ps_decode_buffer[current_write_index].write_pos, buf, stream->ps_decode_buffer[current_write_index].size - stream->ps_decode_buffer[current_write_index].write_pos);
- written += stream->ps_decode_buffer[current_write_index].size - stream->ps_decode_buffer[current_write_index].write_pos;
- stream->ps_decode_buffer[current_write_index].write_pos += stream->ps_decode_buffer[current_write_index].size - stream->ps_decode_buffer[current_write_index].write_pos;
- stream->ps_decode_buffer[current_write_index].len = stream->ps_decode_buffer[current_write_index].write_pos;
-
- if (flushbuf(stream))
- {
- // FLushing the buffer will have change the current write buffer
- current_write_index = stream->ps_current_write_buffer_index;
-
- memcpy(stream->ps_decode_buffer[current_write_index].data, (unsigned char*)buf + written, size - written);
- stream->ps_decode_buffer[current_write_index].write_pos += size - written;
- stream->ps_decode_buffer[current_write_index].len = stream->ps_decode_buffer[current_write_index].write_pos;
- written += size - written;
- }
- }
-
-
- if (elnum == 1 && written == size)
- return 1;
- else
- return written / elsize;
-}
-
-static int write_pack(hb_stream_t* stream, int64_t time)
-{
- unsigned char buf[64];
- set_buf(buf, 64, 1); // clear buffer
-
- int64_t ext_time = time % 300;
- time = time / 300;
-
- set_bits(0x000001ba, 32); // pack id 32
- set_bits(1, 2); // 0x01 2
- set_bits((unsigned int)(time >> 30), 3); // system_clock_reference_base 3
- set_bits(1, 1); // marker_bit 1
- set_bits((unsigned int)(time >> 15), 15); // system_clock_reference_base 15
- set_bits(1, 1); // marker_bit 1
- set_bits((unsigned int)time, 15); // system_clock_reference_base1 15
- set_bits(1, 1); // marker_bit 1
- set_bits((unsigned int)ext_time, 9); // system_clock_reference_extension 9
- set_bits(1, 1); // marker_bit 1
- set_bits(DEMUX, 22); // program_mux_rate 22
- set_bits(1, 1); // marker_bit 1
- set_bits(1, 1); // marker_bit 1
- set_bits(31, 5); // reserved 5
- set_bits(0, 3); // pack_stuffing_length 3
-
- return fwrite64(buf, buf_size(), 1, stream) == 1;
-}
-
-static int pad_buffer(hb_stream_t *stream, int pad)
-{
- pad -= 6;
-
- char buf[6];
- buf[0] = '\x0'; buf[1] = '\x0'; buf[2] = '\x1'; buf[3] = '\xbe';
- buf[4] = pad >> 8; buf[5] = pad & 0xff;
-
- if (fwrite64(buf, 6, 1, stream) != 1)
- return 0;
-
- unsigned char padbyte = 0xff;
- int i=0;
- for (i = 0; i < pad; i++)
- {
- if (fwrite64(&padbyte, 1, 1, stream) != 1)
- return 0;
- }
-
- return 1;
-}
-
-int make_pes_header(unsigned char* buf, int streamid, int len, int64_t PTS, int64_t DTS)
-{
- int hdrlen = 0;
- int PTS_DTS_flags = 0;
- if (PTS != -1)
- {
- if (DTS != -1)
- {
- PTS_DTS_flags = 3;
- hdrlen += 10;
- }
- else
- {
- PTS_DTS_flags = 2;
- hdrlen += 5;
- }
- }
-
- set_buf(buf, 9 + hdrlen, 1); // clear the buffer
-
- set_bits(0x000001, 24); // packet_start_code_prefix 24
- set_bits((unsigned int)streamid, 8); // directory_stream_id 8
- set_bits(len, 16); // PES_packet_length 16
- set_bits(0x2, 2); // '10' 2
- set_bits(0, 2); // PES_scrambling_control 2
- set_bits(1, 1); // PES_priority 1
- set_bits(0, 1); // data_alignment_indicator 1
- set_bits(0, 1); // copyright 1
- set_bits(0, 1); // original_or_copy 1
- set_bits(PTS_DTS_flags, 2); // PTS_DTS_flags 2
- set_bits(0, 1); // ESCR_flag 1
- set_bits(0, 1); // ES_rate_flag 1
- set_bits(0, 1); // DSM_trick_mode_flag 1
- set_bits(0, 1); // additional_copy_info_flag 1
- set_bits(0, 1); // PES_CRC_flag 1
- set_bits(0, 1); // PES_extension_flag 1
- set_bits(hdrlen, 8); // PES_header_data_length 8
-
- if (PTS_DTS_flags == 2)
- {
- set_bits(2, 4); // '0010' 4
- set_bits((unsigned int)(PTS >> 30), 3); // PTS [32..30] 3
- set_bits(1, 1); // marker bit 1
- set_bits((unsigned int)(PTS >> 15), 15); // PTS [29..15] 15
- set_bits(1, 1); // marker bit 1
- set_bits((unsigned int)PTS, 15); // PTS [14..0] 15
- set_bits(1, 1); // marker bit 1
- }
- else if (PTS_DTS_flags == 3)
- {
- set_bits(3, 4); // '0011' 4
- set_bits((unsigned int)(PTS >> 30), 3); // PTS [32..30] 3
- set_bits(1, 1); // marker bit 1
- set_bits((unsigned int)(PTS >> 15), 15); // PTS [29..15] 15
- set_bits(1, 1); // marker bit 1
- set_bits((unsigned int)PTS, 15); // PTS [14..0] 15
- set_bits(1, 1); // marker bit 1
- set_bits(1, 4); // '0001' 4
- set_bits((unsigned int)(DTS >> 30), 3); // DTS [32..30] 3
- set_bits(1, 1); // marker bit 1
- set_bits((unsigned int)(DTS >> 15), 15); // DTS [29..15] 15
- set_bits(1, 1); // marker bit 1
- set_bits((unsigned int)DTS, 15); // DTS [14..0] 15
- set_bits(1, 1); // marker bit 1
- }
-
- return buf_size();
-}
-
-int generate_output_data(hb_stream_t *stream, int write_ac3, int curstream, int pid)
-{
- unsigned char ac3_substream_id[4];
- int ac3len = 0;
-
- if (write_ac3)
- {
- // Make a four byte DVD ac3 stream header
- int ssid = (curstream - stream->ts_number_video_pids) & 0xf;
- ac3_substream_id[0] = 0x80 | ssid; // substream id
- ac3_substream_id[1] = 0x01; // number of sync words
- ac3_substream_id[2] = 0x00; // first offset (16 bits)
- ac3_substream_id[3] = 0x02;
- ac3len = 4;
- }
-
- int written = 0; // Bytes we've written to output file
- int pos = 0; // Position in PES packet buffer
-
- for (;;)
- {
- if ((stream->ps_decode_buffer[stream->ps_current_write_buffer_index].len % HB_DVD_READ_BUFFER_SIZE) != 0)
- {
- hb_log("write_output_stream - Packet's not falling on read buffer size boundries!");
- return 1;
- }
-
- // Get total length of this pack
- int len = min(14 + ac3len + stream->ts_packetpos[curstream] - pos, HB_DVD_READ_BUFFER_SIZE);
-
- // Figure out stuffing (if we have less than 16 bytes left)
- int stuffing = 0;
- if (len < HB_DVD_READ_BUFFER_SIZE && HB_DVD_READ_BUFFER_SIZE - len < 16)
- {
- stuffing = HB_DVD_READ_BUFFER_SIZE - len;
- len += stuffing;
- }
-
- // Write out pack header
- off_t file_offset = ftello(stream->file_handle);
- int64_t packet_time = (file_offset * CLOCKRATE / STREAMRATE) + 0 /*file_time*/;
- if (!write_pack(stream, packet_time))
- {
- hb_log("write_output_stream - Couldn't write pack header!");
- return 1;
- }
-
- int index_of_selected_pid = -1;
- if ((index_of_selected_pid = index_of_video_pid(pid,stream)) < 0)
- {
- if ((index_of_selected_pid = index_of_audio_pid(pid,stream)) < 0)
- {
- hb_log("generate_output_data - cannot find pid 0x%x (%d) in selected audio or video pids", pid, pid);
- return 0;
- }
- else
- {
- stream->ts_packetbuf[curstream][pos + 3] = stream->ts_streamid[stream->ts_number_video_pids + index_of_selected_pid];
- }
- }
- else
- stream->ts_packetbuf[curstream][pos + 3] = stream->ts_streamid[index_of_selected_pid];
-
- // Packet length..
- // Subtract pack size (14) and pes id and len (6) from lenth
- stream->ts_packetbuf[curstream][pos + 4] = (len - 6 - 14) >> 8; stream->ts_packetbuf[curstream][pos + 5] = (len - 6 - 14) & 0xFF;
-
- // Add any stuffing bytes to header extra len
- int hdrsize = 9 + stream->ts_packetbuf[curstream][pos + 8];
- stream->ts_packetbuf[curstream][pos + 8] += stuffing; // Add stuffing to header bytes
-
- // Write out id, streamid, len
- if (fwrite64(stream->ts_packetbuf[curstream] + pos, hdrsize, 1, stream) != 1) // Write pes id, streamid, and len
- {
- hb_log("write_output_stream - Failed to write output file!");
- return 1;
- }
-
- // Write stuffing
- int i=0;
- for (i = 0; i < stuffing; i++) // Write any stuffing bytes
- {
- unsigned char stuff = 0xff;
- if (fwrite64(&stuff, 1, 1, stream) != 1)
- {
- hb_log("write_output_stream - Failed to write output file!");
- return 1;
- }
- }
-
- // Write ac3 streamid
- if (ac3len != 0)
- {
- if (fwrite64(ac3_substream_id, ac3len, 1, stream) != 1)
- {
- hb_log("write_output_stream - Failed to write output file!");
- return 1;
- }
- }
-
- // Write rest of data len minus headersize (9) stuffing, and pack size (14)
- if (fwrite64(stream->ts_packetbuf[curstream] + pos + hdrsize, len - hdrsize - 14 - stuffing - ac3len, 1, stream) != 1) // Write data bytes
- {
- hb_log("write_output_stream - Failed to write output file!");
- return 1;
- }
- written += len;
-
- // Add len minus stuff we added like the pack (14) and the stuffing.
- pos += len - 14 - stuffing - ac3len;
- if (pos == stream->ts_packetpos[curstream])
- break;
-
- // Add pes header for next packet
- pos -= 9;
-// make_pes_header(stream->ts_packetbuf[curstream] + pos, (pid == stream->ts_video_pids[0] ? stream->ts_streamid[kVideoStream] : stream->ts_streamid[kAudioStream]), 0, -1, -1);
- make_pes_header(stream->ts_packetbuf[curstream] + pos, stream->ts_streamid[curstream], 0, -1, -1);
- }
-
- // Write padding
- if ((written % HB_DVD_READ_BUFFER_SIZE) != 0)
- {
- int left = HB_DVD_READ_BUFFER_SIZE - (written % HB_DVD_READ_BUFFER_SIZE);
-
- // Pad out to HB_DVD_READ_BUFFER_SIZE bytes
- if (!pad_buffer(stream, left))
- {
- hb_log("write_output_stream - Couldn't write pad buffer!");
- return 1;
- }
- }
-
- stream->ts_packetpos[curstream] = 0;
- stream->ts_streamcont[curstream] = -1;
-
- return 0;
-}
-
-static void hb_ts_handle_mpeg_audio(hb_stream_t *stream, int curstream, unsigned char* buf, int adapt_len )
-{
- // Although we don't have AC3/A52 audio here we can still use the same structure to record this useful information.
-
- stream->a52_info[curstream - stream->ts_number_video_pids].flags = A52_STEREO;
- stream->a52_info[curstream - stream->ts_number_video_pids].rate = 48000 /*Hz*/;
- stream->a52_info[curstream - stream->ts_number_video_pids].bitrate = 384000 /*Bps*/;
-}
-
-static int hb_ts_handle_ac3_audio(hb_stream_t *stream, int curstream, unsigned char* buf, int adapt_len )
-{
- int spos, dpos;
-
- // Make sure we start with 0x0b77
- if (stream->ts_packetbuf[curstream][9 + stream->ts_packetbuf[curstream][8]] != 0x0b || stream->ts_packetbuf[curstream][9 + stream->ts_packetbuf[curstream][8] + 1] != 0x77)
- {
- spos = 9 + stream->ts_packetbuf[curstream][8];
- dpos = 9 + stream->ts_packetbuf[curstream][8];
- while (spos <= stream->ts_packetpos[curstream] - 2 && !(stream->ts_packetbuf[curstream][spos] == 0x0b && stream->ts_packetbuf[curstream][spos + 1] == 0x77))
- spos++;
-
- if (!(stream->ts_packetbuf[curstream][spos] == 0x0b && stream->ts_packetbuf[curstream][spos + 1] == 0x77))
- {
- hb_log("hb_ts_stream_decode - Couldn't sync AC3 packet!");
- stream->ts_skipbad[curstream] = 1;
- return 0;
- }
-
- while (spos < stream->ts_packetpos[curstream])
- {
- stream->ts_packetbuf[curstream][dpos] = stream->ts_packetbuf[curstream][spos];
- spos++;
- dpos++;
- }
- stream->ts_packetpos[curstream] = dpos;
- }
-
- // Check the next packet to make sure IT starts with a 0x0b77
- int plen = 0;
-// if (buf[4 + adapt_len] == 0 && buf[4 + adapt_len + 1] == 0 && // Starting with an mpeg header?
-// buf[4 + adapt_len + 2] == 1 && buf[4 + adapt_len + 3] == 0xBD)
- plen = 9 + buf[4 + adapt_len + 8];
- int pstart = 4 + adapt_len + plen;
- if (buf[pstart] != 0x0b || buf[pstart + 1] != 0x77)
- {
- spos = pstart;
- while (spos < 188 - 2 && !(buf[spos] == 0x0b && buf[spos + 1] == 0x77))
- {
- stream->ts_packetbuf[curstream][stream->ts_packetpos[curstream]] = buf[spos];
- stream->ts_packetpos[curstream]++;
- spos++;
- }
-
- if (!(buf[spos] == 0x0b && buf[spos + 1] == 0x77))
- {
- hb_log("hb_ts_stream_decode - Couldn't sync AC3 packet!");
- stream->ts_skipbad[curstream] = 1;
- return 0;
- }
-
- adapt_len = spos - 4 - plen;
-
- dpos = spos - 1;
- spos = pstart - 1;
- while (spos >= pstart - plen)
- {
- buf[dpos] = buf[spos];
- spos--;
- dpos--;
- }
- }
-
- int flags, rate, bitrate;
- if( a52_syncinfo( &buf[pstart], &flags, &rate, &bitrate ) )
- {
- stream->a52_info[curstream - stream->ts_number_video_pids].flags = flags;
- stream->a52_info[curstream - stream->ts_number_video_pids].rate = rate;
- stream->a52_info[curstream - stream->ts_number_video_pids].bitrate = bitrate;
- }
- return 1;
-}
-