summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2005-09-04 21:55:15 +0000
committerJens Arnold <amiconn@rockbox.org>2005-09-04 21:55:15 +0000
commit9352ac86680a2507b657c141029d831447f1bed8 (patch)
treeaab63cecd6cf9a6198c8d3fea202f41b63569668
parentb7caf5ba6321b7a42bab113b571c5968ac3af064 (diff)
downloadrockbox-9352ac86680a2507b657c141029d831447f1bed8.tar.gz
rockbox-9352ac86680a2507b657c141029d831447f1bed8.zip
Archos recording: Always prepend ID3V2 and Xing header to a recording file, even with prerecording and file splitting. Adjusted Xing header creation to create smaller headers. Fixed missing break; in the mpeg thread.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7472 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/export/mp3data.h2
-rw-r--r--firmware/export/mpeg.h2
-rw-r--r--firmware/mp3data.c39
-rw-r--r--firmware/mpeg.c312
4 files changed, 184 insertions, 171 deletions
diff --git a/firmware/export/mp3data.h b/firmware/export/mp3data.h
index a7f2e3d7f0..db1a93b8d6 100644
--- a/firmware/export/mp3data.h
+++ b/firmware/export/mp3data.h
@@ -57,6 +57,8 @@ struct mp3info {
57#define VBR_TOC_FLAG 0x04 57#define VBR_TOC_FLAG 0x04
58#define VBR_QUALITY_FLAG 0x08 58#define VBR_QUALITY_FLAG 0x08
59 59
60#define MAX_XING_HEADER_SIZE 288
61
60unsigned long find_next_frame(int fd, long *offset, long max_offset, unsigned long last_header); 62unsigned long find_next_frame(int fd, long *offset, long max_offset, unsigned long last_header);
61unsigned long mem_find_next_frame(int startpos, long *offset, long max_offset, 63unsigned long mem_find_next_frame(int startpos, long *offset, long max_offset,
62 unsigned long last_header); 64 unsigned long last_header);
diff --git a/firmware/export/mpeg.h b/firmware/export/mpeg.h
index 6ce3b47275..a0ad3c405c 100644
--- a/firmware/export/mpeg.h
+++ b/firmware/export/mpeg.h
@@ -41,7 +41,7 @@
41#define MPEG_MAX_PRERECORD_SECONDS 30 41#define MPEG_MAX_PRERECORD_SECONDS 30
42 42
43/* For ID3 info and VBR header */ 43/* For ID3 info and VBR header */
44#define MPEG_RESERVED_HEADER_SPACE (4096 + 1500) 44#define MPEG_RESERVED_HEADER_SPACE (4096 + 288)
45 45
46#if (CONFIG_CODEC == MAS3587F) || defined(SIMULATOR) 46#if (CONFIG_CODEC == MAS3587F) || defined(SIMULATOR)
47void mpeg_init_recording(void); 47void mpeg_init_recording(void);
diff --git a/firmware/mp3data.c b/firmware/mp3data.c
index 44c298a463..6f4c560578 100644
--- a/firmware/mp3data.c
+++ b/firmware/mp3data.c
@@ -607,8 +607,8 @@ int count_mp3_frames(int fd, int startpos, int filesize,
607static const char cooltext[] = "Rockbox - rocks your box"; 607static const char cooltext[] = "Rockbox - rocks your box";
608 608
609int create_xing_header(int fd, int startpos, int filesize, 609int create_xing_header(int fd, int startpos, int filesize,
610 unsigned char *buf, int num_frames, 610 unsigned char *buf, /* must be at least 288 bytes */
611 unsigned long header_template, 611 int num_frames, unsigned long header_template,
612 void (*progressfunc)(int), bool generate_toc) 612 void (*progressfunc)(int), bool generate_toc)
613{ 613{
614 unsigned long header = 0; 614 unsigned long header = 0;
@@ -691,35 +691,40 @@ int create_xing_header(int fd, int startpos, int filesize,
691 last_pos = pos; 691 last_pos = pos;
692 } 692 }
693 } 693 }
694 694
695 /* Use the template header and create a new one. 695 /* Check the template header for validity and get some preliminary info. */
696 We ignore the Protection bit even if the rest of the stream is 696 if (!mp3headerinfo(&info, xing_header_template))
697 protected. (fixme?) */ 697 return 0; /* invalid header */
698 header = xing_header_template & ~(BITRATE_MASK | PROTECTION_MASK);
699 header |= 8 << 12; /* This gives us plenty of space, at least 192 bytes */
700
701 if (!mp3headerinfo(&info, header))
702 return 0; /* invalid header */
703 698
704 /* Clear the frame */ 699 /* Clear the frame */
705 memset(buf, 0, 1500); 700 memset(buf, 0, MAX_XING_HEADER_SIZE);
706 701
707 /* Write the header to the buffer */ 702 /* Use the template header and create a new one. */
708 long2bytes(buf, header); 703 header = xing_header_template & ~(BITRATE_MASK | PROTECTION_MASK);
709 704
710 /* calculate position of VBR header */ 705 /* Calculate position of VBR header and required frame bitrate */
711 if ( info.version == MPEG_VERSION1 ) { 706 if (info.version == MPEG_VERSION1) {
707 header |= 5 << 12;
712 if (info.channel_mode == 3) /* mono */ 708 if (info.channel_mode == 3) /* mono */
713 index = 21; 709 index = 21;
714 else 710 else
715 index = 36; 711 index = 36;
716 } 712 }
717 else { 713 else {
714 if (info.version == MPEG_VERSION2)
715 header |= 8 << 12;
716 else /* MPEG_VERSION2_5 */
717 header |= 4 << 12;
718 if (info.channel_mode == 3) /* mono */ 718 if (info.channel_mode == 3) /* mono */
719 index = 13; 719 index = 13;
720 else 720 else
721 index = 21; 721 index = 21;
722 } 722 }
723 mp3headerinfo(&info, header); /* Get final header info */
724 /* Size is now always one of 192, 208 or 288 bytes */
725
726 /* Write the header to the buffer */
727 long2bytes(buf, header);
723 728
724 /* Create the Xing data */ 729 /* Create the Xing data */
725 memcpy(&buf[index], "Xing", 4); 730 memcpy(&buf[index], "Xing", 4);
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index cd413d60fd..831463a671 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -65,24 +65,25 @@ extern int playlist_next(int steps);
65extern int playlist_amount(void); 65extern int playlist_amount(void);
66extern int playlist_update_resume_info(const struct mp3entry* id3); 66extern int playlist_update_resume_info(const struct mp3entry* id3);
67 67
68#define MPEG_PLAY 1 68#define MPEG_PLAY 1
69#define MPEG_STOP 2 69#define MPEG_STOP 2
70#define MPEG_PAUSE 3 70#define MPEG_PAUSE 3
71#define MPEG_RESUME 4 71#define MPEG_RESUME 4
72#define MPEG_NEXT 5 72#define MPEG_NEXT 5
73#define MPEG_PREV 6 73#define MPEG_PREV 6
74#define MPEG_FF_REWIND 7 74#define MPEG_FF_REWIND 7
75#define MPEG_FLUSH_RELOAD 8 75#define MPEG_FLUSH_RELOAD 8
76#define MPEG_RECORD 9 76#define MPEG_RECORD 9
77#define MPEG_INIT_RECORDING 10 77#define MPEG_INIT_RECORDING 10
78#define MPEG_INIT_PLAYBACK 11 78#define MPEG_INIT_PLAYBACK 11
79#define MPEG_NEW_FILE 12 79#define MPEG_NEW_FILE 12
80#define MPEG_PAUSE_RECORDING 13 80#define MPEG_PAUSE_RECORDING 13
81#define MPEG_RESUME_RECORDING 14 81#define MPEG_RESUME_RECORDING 14
82#define MPEG_NEED_DATA 100 82#define MPEG_NEED_DATA 100
83#define MPEG_TRACK_CHANGE 101 83#define MPEG_TRACK_CHANGE 101
84#define MPEG_SAVE_DATA 102 84#define MPEG_SAVE_DATA 102
85#define MPEG_STOP_DONE 103 85#define MPEG_STOP_DONE 103
86#define MPEG_PRERECORDING_TICK 104
86 87
87/* indicator for MPEG_NEED_DATA */ 88/* indicator for MPEG_NEED_DATA */
88#define GENERATE_UNBUFFER_EVENTS ((void*)1) 89#define GENERATE_UNBUFFER_EVENTS ((void*)1)
@@ -155,12 +156,13 @@ static long lowest_watermark_level; /* Debug value to observe the buffer
155static char recording_filename[MAX_PATH]; /* argument to thread */ 156static char recording_filename[MAX_PATH]; /* argument to thread */
156static char delayed_filename[MAX_PATH]; /* internal copy of above */ 157static char delayed_filename[MAX_PATH]; /* internal copy of above */
157 158
159static char xing_buffer[MAX_XING_HEADER_SIZE];
160
158static bool init_recording_done; 161static bool init_recording_done;
159static bool init_playback_done; 162static bool init_playback_done;
160static bool prerecording; /* True if prerecording is enabled */ 163static bool prerecording; /* True if prerecording is enabled */
161static bool is_prerecording; /* True if we are prerecording */ 164static bool is_prerecording; /* True if we are prerecording */
162static bool is_recording; /* We are recording */ 165static bool is_recording; /* We are recording */
163static bool disable_xing_header; /* When splitting files */
164 166
165static enum { 167static enum {
166 NOT_SAVING = 0, /* reasons to save data, sorted by importance */ 168 NOT_SAVING = 0, /* reasons to save data, sorted by importance */
@@ -172,8 +174,12 @@ static enum {
172static int rec_frequency_index; /* For create_xing_header() calls */ 174static int rec_frequency_index; /* For create_xing_header() calls */
173static int rec_version_index; /* For create_xing_header() calls */ 175static int rec_version_index; /* For create_xing_header() calls */
174 176
175static int prerecord_buffer[MPEG_MAX_PRERECORD_SECONDS]; 177struct prerecord_info {
176 /* Array of buffer indexes for each prerecorded second */ 178 int mempos;
179 unsigned long framecount;
180};
181
182static struct prerecord_info prerecord_buffer[MPEG_MAX_PRERECORD_SECONDS];
177static int prerecord_index; /* Current index in the prerecord buffer */ 183static int prerecord_index; /* Current index in the prerecord buffer */
178static int prerecording_max_seconds; /* Max number of seconds to store */ 184static int prerecording_max_seconds; /* Max number of seconds to store */
179static int prerecord_count; /* Number of seconds in the prerecord buffer */ 185static int prerecord_count; /* Number of seconds in the prerecord buffer */
@@ -185,7 +191,10 @@ unsigned long record_start_time; /* Value of current_tick when recording
185unsigned long pause_start_time; /* Value of current_tick when pause was 191unsigned long pause_start_time; /* Value of current_tick when pause was
186 started */ 192 started */
187static unsigned long num_rec_bytes; 193static unsigned long num_rec_bytes;
188static unsigned long num_recorded_frames; 194static unsigned long last_rec_bytes;
195static unsigned long frame_count_start;
196static unsigned long frame_count_end;
197static unsigned long saved_header = 0;
189 198
190/* Shadow MAS registers */ 199/* Shadow MAS registers */
191unsigned long shadow_encoder_control = 0; 200unsigned long shadow_encoder_control = 0;
@@ -213,6 +222,8 @@ static int get_unswapped_space(void);
213 222
214#if CONFIG_CODEC == MAS3587F 223#if CONFIG_CODEC == MAS3587F
215static void init_recording(void); 224static void init_recording(void);
225static void prepend_header(void);
226static void update_header(void);
216static void start_prerecording(void); 227static void start_prerecording(void);
217static void start_recording(void); 228static void start_recording(void);
218static void stop_recording(void); 229static void stop_recording(void);
@@ -745,17 +756,8 @@ void rec_tick(void)
745 if(TIME_AFTER(current_tick, prerecord_timeout)) 756 if(TIME_AFTER(current_tick, prerecord_timeout))
746 { 757 {
747 prerecord_timeout = current_tick + HZ; 758 prerecord_timeout = current_tick + HZ;
748 759 queue_post(&mpeg_queue, MPEG_PRERECORDING_TICK, 0);
749 /* Store the write pointer every second */ 760 wake_up_thread();
750 prerecord_buffer[prerecord_index++] = audiobuf_write;
751
752 /* Wrap if necessary */
753 if(prerecord_index == prerecording_max_seconds)
754 prerecord_index = 0;
755
756 /* Update the number of seconds recorded */
757 if(prerecord_count < prerecording_max_seconds)
758 prerecord_count++;
759 } 761 }
760 } 762 }
761 else 763 else
@@ -1164,10 +1166,9 @@ static void mpeg_thread(void)
1164 int start_offset; 1166 int start_offset;
1165#if CONFIG_CODEC == MAS3587F 1167#if CONFIG_CODEC == MAS3587F
1166 int amount_to_save; 1168 int amount_to_save;
1167 int framelen;
1168 unsigned long saved_header = 0;
1169 int save_endpos = 0; 1169 int save_endpos = 0;
1170 int rc; 1170 int rc;
1171 int level;
1171 long offset; 1172 long offset;
1172#endif /* CONFIG_CODEC == MAS3587F */ 1173#endif /* CONFIG_CODEC == MAS3587F */
1173 1174
@@ -1749,26 +1750,25 @@ static void mpeg_thread(void)
1749 switch(ev.id) 1750 switch(ev.id)
1750 { 1751 {
1751 case MPEG_RECORD: 1752 case MPEG_RECORD:
1752 if(is_prerecording) 1753 if (is_prerecording)
1753 { 1754 {
1754 int startpos, i; 1755 int startpos;
1755 int level; 1756
1756
1757 /* Go back prerecord_count seconds in the buffer */ 1757 /* Go back prerecord_count seconds in the buffer */
1758 startpos = prerecord_index - prerecord_count; 1758 startpos = prerecord_index - prerecord_count;
1759 if(startpos < 0) 1759 if(startpos < 0)
1760 startpos += prerecording_max_seconds; 1760 startpos += prerecording_max_seconds;
1761 1761
1762 /* Read the mp3 buffer pointer from the prerecord 1762 /* Read the position data from the prerecord buffer */
1763 buffer */ 1763 frame_count_start = prerecord_buffer[startpos].framecount;
1764 startpos = prerecord_buffer[startpos]; 1764 startpos = prerecord_buffer[startpos].mempos;
1765 1765
1766 DEBUGF("Start looking at address %x (%x)\n", 1766 DEBUGF("Start looking at address %x (%x)\n",
1767 audiobuf+startpos, startpos); 1767 audiobuf+startpos, startpos);
1768 1768
1769 saved_header = mpeg_get_last_header(); 1769 saved_header = mpeg_get_last_header();
1770 1770
1771 mem_find_next_frame(startpos, &offset, 5000, 1771 mem_find_next_frame(startpos, &offset, 1800,
1772 saved_header); 1772 saved_header);
1773 1773
1774 audiobuf_read = startpos + offset; 1774 audiobuf_read = startpos + offset;
@@ -1781,58 +1781,17 @@ static void mpeg_thread(void)
1781 level = set_irq_level(HIGHEST_IRQ_LEVEL); 1781 level = set_irq_level(HIGHEST_IRQ_LEVEL);
1782 num_rec_bytes = get_unsaved_space(); 1782 num_rec_bytes = get_unsaved_space();
1783 set_irq_level(level); 1783 set_irq_level(level);
1784
1785 /* Make room for headers */
1786 audiobuf_read -= MPEG_RESERVED_HEADER_SPACE;
1787 if(audiobuf_read < 0)
1788 {
1789 /* Clear the bottom half */
1790 memset(audiobuf, 0,
1791 audiobuf_read + MPEG_RESERVED_HEADER_SPACE);
1792
1793 /* And the top half */
1794 audiobuf_read += audiobuflen;
1795 memset(audiobuf + audiobuf_read, 0,
1796 audiobuflen - audiobuf_read);
1797 }
1798 else
1799 {
1800 memset(audiobuf + audiobuf_read, 0,
1801 MPEG_RESERVED_HEADER_SPACE);
1802 }
1803
1804 /* Copy the empty ID3 header */
1805 startpos = audiobuf_read;
1806 for(i = 0;i < (int)sizeof(empty_id3_header);i++)
1807 {
1808 audiobuf[startpos++] = empty_id3_header[i];
1809 if(startpos == audiobuflen)
1810 startpos = 0;
1811 }
1812
1813 DEBUGF("New audiobuf_read address (reservation): %x\n",
1814 audiobuf+audiobuf_read);
1815
1816 DEBUGF("Prerecording...\n");
1817 } 1784 }
1818 else 1785 else
1819 { 1786 {
1820 reset_mp3_buffer(); 1787 frame_count_start = 0;
1821
1822 num_rec_bytes = 0; 1788 num_rec_bytes = 0;
1823 1789 audiobuf_read = MPEG_RESERVED_HEADER_SPACE;
1824 /* Advance the write pointer to make
1825 room for an ID3 tag plus a VBR header */
1826 audiobuf_write = MPEG_RESERVED_HEADER_SPACE; 1790 audiobuf_write = MPEG_RESERVED_HEADER_SPACE;
1827 memset(audiobuf, 0, MPEG_RESERVED_HEADER_SPACE);
1828
1829 /* Insert the ID3 header */
1830 memcpy(audiobuf, empty_id3_header,
1831 sizeof(empty_id3_header));
1832
1833 DEBUGF("Recording...\n");
1834 } 1791 }
1835 1792
1793 prepend_header();
1794 DEBUGF("Recording...\n");
1836 start_recording(); 1795 start_recording();
1837 1796
1838 /* Wait until at least one frame is encoded and get the 1797 /* Wait until at least one frame is encoded and get the
@@ -1840,7 +1799,7 @@ static void mpeg_thread(void)
1840 generation */ 1799 generation */
1841 sleep(HZ/5); 1800 sleep(HZ/5);
1842 saved_header = mpeg_get_last_header(); 1801 saved_header = mpeg_get_last_header();
1843 1802
1844 /* delayed until buffer is saved, don't open yet */ 1803 /* delayed until buffer is saved, don't open yet */
1845 strcpy(delayed_filename, recording_filename); 1804 strcpy(delayed_filename, recording_filename);
1846 mpeg_file = -1; 1805 mpeg_file = -1;
@@ -1863,40 +1822,9 @@ static void mpeg_thread(void)
1863 1822
1864 if (mpeg_file >= 0) 1823 if (mpeg_file >= 0)
1865 close(mpeg_file); 1824 close(mpeg_file);
1866
1867 if (!disable_xing_header && num_rec_bytes > 0)
1868 {
1869 /* Create the Xing header */
1870 mpeg_file = open(recording_filename, O_RDWR);
1871 if (mpeg_file < 0)
1872 panicf("rec upd: %d (%s)", mpeg_file,
1873 recording_filename);
1874
1875 /* If the number of recorded frames have
1876 reached 0x7ffff, we can no longer trust it */
1877 if (num_recorded_frames == 0x7ffff)
1878 num_recorded_frames = 0;
1879
1880 /* Also, if we have been prerecording, the frame count
1881 will be wrong */
1882 if (prerecording)
1883 num_recorded_frames = 0;
1884
1885 /* saved_header is saved right before stopping
1886 the MAS */
1887 framelen = create_xing_header(mpeg_file, 0,
1888 num_rec_bytes, audiobuf,
1889 num_recorded_frames,
1890 saved_header, NULL,
1891 false);
1892
1893 lseek(mpeg_file, MPEG_RESERVED_HEADER_SPACE-framelen,
1894 SEEK_SET);
1895 write(mpeg_file, audiobuf, framelen);
1896 close(mpeg_file);
1897 }
1898 mpeg_file = -1; 1825 mpeg_file = -1;
1899 1826
1827 update_header();
1900#ifdef DEBUG1 1828#ifdef DEBUG1
1901 { 1829 {
1902 int i; 1830 int i;
@@ -1934,37 +1862,41 @@ static void mpeg_thread(void)
1934 amount_to_save = get_unsaved_space(); 1862 amount_to_save = get_unsaved_space();
1935 } 1863 }
1936 1864
1865 mas_readmem(MAS_BANK_D0, MAS_D0_MPEG_FRAME_COUNT,
1866 &frame_count_end, 1);
1867
1868 /* capture all values at one point */
1869 level = set_irq_level(HIGHEST_IRQ_LEVEL);
1870 save_endpos = audiobuf_write;
1871 last_rec_bytes = num_rec_bytes;
1872 num_rec_bytes = 0;
1873 set_irq_level(level);
1874
1937 if (amount_to_save >= 1800) 1875 if (amount_to_save >= 1800)
1938 { 1876 {
1939 /* Now find a frame boundary to split at */ 1877 /* Now find a frame boundary to split at */
1940 save_endpos = audiobuf_write - 1800; 1878 save_endpos -= 1800;
1941 if (save_endpos < 0) 1879 if (save_endpos < 0)
1942 save_endpos += audiobuflen; 1880 save_endpos += audiobuflen;
1943 1881
1944 rc = mem_find_next_frame(save_endpos, &offset, 1800, 1882 rc = mem_find_next_frame(save_endpos, &offset, 1800,
1945 saved_header); 1883 saved_header);
1946 if (rc) /* Header found? */ 1884 if (!rc) /* No header found, save whole buffer */
1947 { 1885 offset = 1800;
1948 /* offset will now contain the number of bytes to 1886
1949 add to startpos to find the frame boundary */ 1887 save_endpos += offset;
1950 save_endpos += offset; 1888 if (save_endpos >= audiobuflen)
1951 if (save_endpos >= audiobuflen) 1889 save_endpos -= audiobuflen;
1952 save_endpos -= audiobuflen; 1890
1953 } 1891 last_rec_bytes += offset - 1800;
1954 else 1892 level = set_irq_level(HIGHEST_IRQ_LEVEL);
1955 { 1893 num_rec_bytes += 1800 - offset;
1956 /* No header found. Let's save the whole buffer. */ 1894 set_irq_level(level);
1957 save_endpos = audiobuf_write;
1958 }
1959 }
1960 else
1961 {
1962 /* Too few bytes recorded, timeout */
1963 save_endpos = audiobuf_write;
1964 } 1895 }
1965 1896
1966 saving_status = NEW_FILE; 1897 saving_status = NEW_FILE;
1967 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0); 1898 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
1899 break;
1968 1900
1969 case MPEG_SAVE_DATA: 1901 case MPEG_SAVE_DATA:
1970 if (saving_status == BUFFER_FULL) 1902 if (saving_status == BUFFER_FULL)
@@ -2025,18 +1957,22 @@ static void mpeg_thread(void)
2025 /* Close the current file */ 1957 /* Close the current file */
2026 rc = close(mpeg_file); 1958 rc = close(mpeg_file);
2027 if (rc < 0) 1959 if (rc < 0)
2028 panicf("spt cls: %d", rc); 1960 panicf("rec cls: %d", rc);
2029 ata_sleep();
2030 mpeg_file = -1; 1961 mpeg_file = -1;
1962 update_header();
1963 ata_sleep();
1964
2031 /* copy new filename */ 1965 /* copy new filename */
2032 strcpy(delayed_filename, recording_filename); 1966 strcpy(delayed_filename, recording_filename);
1967 prepend_header();
1968 frame_count_start = frame_count_end;
2033 break; 1969 break;
2034 1970
2035 case STOP_RECORDING: 1971 case STOP_RECORDING:
2036 queue_post(&mpeg_queue, MPEG_STOP_DONE, NULL); 1972 queue_post(&mpeg_queue, MPEG_STOP_DONE, NULL);
2037 /* will close the file */ 1973 /* will close the file */
2038 break; 1974 break;
2039 1975
2040 default: 1976 default:
2041 break; 1977 break;
2042 } 1978 }
@@ -2046,6 +1982,24 @@ static void mpeg_thread(void)
2046 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0); 1982 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
2047 1983
2048 break; 1984 break;
1985
1986 case MPEG_PRERECORDING_TICK:
1987 if(!is_prerecording)
1988 break;
1989
1990 /* Store the write pointer every second */
1991 prerecord_buffer[prerecord_index].mempos = audiobuf_write;
1992 mas_readmem(MAS_BANK_D0, MAS_D0_MPEG_FRAME_COUNT,
1993 &prerecord_buffer[prerecord_index].framecount, 1);
1994
1995 /* Wrap if necessary */
1996 if(++prerecord_index == prerecording_max_seconds)
1997 prerecord_index = 0;
1998
1999 /* Update the number of seconds recorded */
2000 if(prerecord_count < prerecording_max_seconds)
2001 prerecord_count++;
2002 break;
2049 2003
2050 case MPEG_INIT_PLAYBACK: 2004 case MPEG_INIT_PLAYBACK:
2051 /* Stop the prerecording */ 2005 /* Stop the prerecording */
@@ -2257,7 +2211,6 @@ void mpeg_record(const char *filename)
2257 strncpy(recording_filename, filename, MAX_PATH - 1); 2211 strncpy(recording_filename, filename, MAX_PATH - 1);
2258 recording_filename[MAX_PATH - 1] = 0; 2212 recording_filename[MAX_PATH - 1] = 0;
2259 2213
2260 disable_xing_header = false;
2261 queue_post(&mpeg_queue, MPEG_RECORD, NULL); 2214 queue_post(&mpeg_queue, MPEG_RECORD, NULL);
2262} 2215}
2263 2216
@@ -2271,6 +2224,64 @@ void mpeg_resume_recording(void)
2271 queue_post(&mpeg_queue, MPEG_RESUME_RECORDING, NULL); 2224 queue_post(&mpeg_queue, MPEG_RESUME_RECORDING, NULL);
2272} 2225}
2273 2226
2227static void prepend_header(void)
2228{
2229 int startpos;
2230 unsigned i;
2231
2232 /* Make room for header */
2233 audiobuf_read -= MPEG_RESERVED_HEADER_SPACE;
2234 if(audiobuf_read < 0)
2235 {
2236 /* Clear the bottom half */
2237 memset(audiobuf, 0, audiobuf_read + MPEG_RESERVED_HEADER_SPACE);
2238
2239 /* And the top half */
2240 audiobuf_read += audiobuflen;
2241 memset(audiobuf + audiobuf_read, 0, audiobuflen - audiobuf_read);
2242 }
2243 else
2244 {
2245 memset(audiobuf + audiobuf_read, 0, MPEG_RESERVED_HEADER_SPACE);
2246 }
2247 /* Copy the empty ID3 header */
2248 startpos = audiobuf_read;
2249 for(i = 0; i < sizeof(empty_id3_header); i++)
2250 {
2251 audiobuf[startpos++] = empty_id3_header[i];
2252 if(startpos == audiobuflen)
2253 startpos = 0;
2254 }
2255}
2256
2257static void update_header(void)
2258{
2259 int fd, framelen;
2260 unsigned long frames;
2261
2262 if (last_rec_bytes > 0)
2263 {
2264 /* Create the Xing header */
2265 fd = open(delayed_filename, O_RDWR);
2266 if (fd < 0)
2267 panicf("rec upd: %d (%s)", fd, recording_filename);
2268
2269 frames = frame_count_end - frame_count_start;
2270 /* If the number of recorded frames has reached 0x7ffff,
2271 we can no longer trust it */
2272 if (frame_count_end == 0x7ffff)
2273 frames = 0;
2274
2275 /* saved_header is saved right before stopping the MAS */
2276 framelen = create_xing_header(fd, 0, last_rec_bytes, xing_buffer,
2277 frames, saved_header, NULL, false);
2278
2279 lseek(fd, MPEG_RESERVED_HEADER_SPACE - framelen, SEEK_SET);
2280 write(fd, xing_buffer, framelen);
2281 close(fd);
2282 }
2283}
2284
2274static void start_prerecording(void) 2285static void start_prerecording(void)
2275{ 2286{
2276 unsigned long val; 2287 unsigned long val;
@@ -2306,8 +2317,6 @@ static void start_recording(void)
2306{ 2317{
2307 unsigned long val; 2318 unsigned long val;
2308 2319
2309 num_recorded_frames = 0;
2310
2311 if(is_prerecording) 2320 if(is_prerecording)
2312 { 2321 {
2313 /* This will make the IRQ handler start recording 2322 /* This will make the IRQ handler start recording
@@ -2386,9 +2395,9 @@ static void stop_recording(void)
2386 2395
2387 is_recording = false; 2396 is_recording = false;
2388 is_prerecording = false; 2397 is_prerecording = false;
2389 2398
2390 /* Read the number of frames recorded */ 2399 last_rec_bytes = num_rec_bytes;
2391 mas_readmem(MAS_BANK_D0, MAS_D0_MPEG_FRAME_COUNT, &num_recorded_frames, 1); 2400 mas_readmem(MAS_BANK_D0, MAS_D0_MPEG_FRAME_COUNT, &frame_count_end, 1);
2392 2401
2393 /* Start monitoring */ 2402 /* Start monitoring */
2394 shadow_io_control_main |= (1 << 10); 2403 shadow_io_control_main |= (1 << 10);
@@ -2514,9 +2523,6 @@ void mpeg_new_file(const char *filename)
2514 strncpy(recording_filename, filename, MAX_PATH - 1); 2523 strncpy(recording_filename, filename, MAX_PATH - 1);
2515 recording_filename[MAX_PATH - 1] = 0; 2524 recording_filename[MAX_PATH - 1] = 0;
2516 2525
2517 num_rec_bytes = 0;
2518 disable_xing_header = true;
2519
2520 /* Store the current time */ 2526 /* Store the current time */
2521 record_start_time = current_tick; 2527 record_start_time = current_tick;
2522 if(paused) 2528 if(paused)
@@ -2554,7 +2560,7 @@ unsigned long mpeg_num_recorded_bytes(void)
2554 if(index < 0) 2560 if(index < 0)
2555 index += prerecording_max_seconds; 2561 index += prerecording_max_seconds;
2556 2562
2557 num_bytes = audiobuf_write - prerecord_buffer[index]; 2563 num_bytes = audiobuf_write - prerecord_buffer[index].mempos;
2558 if(num_bytes < 0) 2564 if(num_bytes < 0)
2559 num_bytes += audiobuflen; 2565 num_bytes += audiobuflen;
2560 2566