I wrote some code that modernizes the MPEG-1 PES header found on D2 MPEG-2 streams:
Code:
int
write_audio(int fd, uint8_t *buf, size_t count)
{
int d, c, ret;
uint8_t buf2[BUFSIZE];
uint16_t pes_header_size;
if((count > (BUFSIZE - 3)) || (count < 12))
return(mywrite(fd, buf, count));
d = -1;
for(c = 0 ; c < 8 ; ++c)
{
if((buf[c] == 0x00) &&
(buf[c + 1] == 0x00) &&
(buf[c + 2] == 0x01) &&
((buf[c + 3] & 0xc0) == 0xc0))
{
d = c;
break;
}
}
if(d == -1)
return(mywrite(fd, buf, count));
/* 0x21 means we're missing the PES header flags (broken S1 stream) */
if((buf[d + 6] & 0x21) != 0x21)
return(mywrite(fd, buf, count));
pes_header_size = buf[d + 5] | (buf[d + 4] << 8);
pes_header_size += 3;
memcpy(buf2, &buf[d], 4); /* prefix code: 00 00 01
* stream id: c0 */
buf2[4] = pes_header_size >> 8; /* 2 bytes: pkt size */
buf2[5] = pes_header_size & 0xff;
/* flags: 80 80
* remaining hdr len: 05
*/
buf2[6] = 0x84; buf2[7] = 0x80; buf2[8] = 0x05;
/* 5 bytes: PTS timestamp */
memcpy(&buf2[9], &buf[d + 6], 5);
/* PES packet data follows */
memcpy(&buf2[14], &buf[11 + d], count - 11 - d);
fprintf(stderr, "real_write ");
for(c = 0 ; c < 20 ; ++c)
{
fprintf(stderr, "%02x ", (int)(unsigned char)buf2[c]);
}
fprintf(stderr, "\n");
ret = mywrite(fd, buf2, count + 3 - d);
if(ret > 0)
ret = count;
return(ret);
}
By intercepting myworld's writes to mpeg0a and rewriting the PES header prior to output, I was able to get sound from inserted D1 streams which were previously silent. However, the audio is either very fast or partially cut off - I only hear pieces of it every few seconds. Those pieces seem to be at least somewhat in sync with the video when they start.
Possibilities include:
- wrong bitrate
- other missing/broken parameters elsewhere in the tystream
- I'm adding a PES header that is not appropriate for the payload?
- buggy code
- something to do with syncing up the video?
Furthermore I have not gotten vplay to play audio reliably on the D2. I've logged a few ioctls that myworld uses to initialize the device, but most of the time I just get silence:
Code:
at startup (only?):
aud_ioctl: 00000456 10102844
aud_ioctl: 000003f0 00000000
aud_ioctl: 000007eb 00000001
aud_ioctl: 000007eb 00000000
aud_ioctl: 00000461 7d1ff8b0 00 00 00 00 00 00 00 01 ff ff ff ff 00 00 00 02 00 00 00 00 00 00 00 41 00 00 00 00 00 00 00 00
aud_ioctl: 000003ef 00000000
aud_ioctl: 00000426 00000000
prior to playing audio stream:
aud_ioctl: 000007eb 00000001
aud_ioctl: 000003f0 0000942c
aud_ioctl: 000007eb 00000000
aud_ioctl: 000003ef 00000000
on occasion, during streams:
aud_ioctl: 00001f46 7d1ff8e8 10 08 2c f0 00 00 00 0b 10 10 27 10 7d 1f f9 88 10 08 2c f0 01 34 ce 58 10 08 2c f0 10 08 2c f0
It's possible that a mixer or some other integrated device needs to be dealt with to properly play sound. I have not looked into this yet. Having a working vplay binary would speed up the testing cycle, as rebooting the box takes several minutes.
Can anyone shed any light on either of these issues?
Many of those ioctls are not documented in (cwingert's?) osdtxt.c, and may be new in the Series 2.