static bool mp3_decode_first_frame(struct mp3_data *data, struct tag **tag, struct replay_gain_info **replay_gain_info_r) { struct xing xing; struct lame lame; struct mad_bitptr ptr; int bitlen; enum mp3_action ret; /* stfu gcc */ memset(&xing, 0, sizeof(struct xing)); xing.flags = 0; while (true) { do { ret = decode_next_frame_header(data, tag, replay_gain_info_r); } while (ret == DECODE_CONT); if (ret == DECODE_BREAK) return false; if (ret == DECODE_SKIP) continue; do { ret = decodeNextFrame(data); } while (ret == DECODE_CONT); if (ret == DECODE_BREAK) return false; if (ret == DECODE_OK) break; } ptr = data->stream.anc_ptr; bitlen = data->stream.anc_bitlen; mp3_filesize_to_song_length(data); /* * if an xing tag exists, use that! */ if (parse_xing(&xing, &ptr, &bitlen)) { data->found_xing = true; data->mute_frame = MUTEFRAME_SKIP; if ((xing.flags & XING_FRAMES) && xing.frames) { mad_timer_t duration = data->frame.header.duration; mad_timer_multiply(&duration, xing.frames); data->total_time = ((float)mad_timer_count(duration, MAD_UNITS_MILLISECONDS)) / 1000; data->max_frames = xing.frames; } if (parse_lame(&lame, &ptr, &bitlen)) { if (gapless_playback && data->input_stream->seekable) { data->drop_start_samples = lame.encoder_delay + DECODERDELAY; data->drop_end_samples = lame.encoder_padding; } /* Album gain isn't currently used. See comment in * parse_lame() for details. -- jat */ if (replay_gain_info_r && !*replay_gain_info_r && lame.track_gain) { *replay_gain_info_r = replay_gain_info_new(); (*replay_gain_info_r)->tuples[REPLAY_GAIN_TRACK].gain = lame.track_gain; (*replay_gain_info_r)->tuples[REPLAY_GAIN_TRACK].peak = lame.peak; } } } if (!data->max_frames) return false; if (data->max_frames > 8 * 1024 * 1024) { g_warning("mp3 file header indicates too many frames: %lu\n", data->max_frames); return false; } data->frame_offsets = g_malloc(sizeof(long) * data->max_frames); data->times = g_malloc(sizeof(mad_timer_t) * data->max_frames); return true; }
xmms_xing_t * xmms_xing_parse (struct mad_bitptr ptr) { xmms_xing_t *xing; guint32 xing_magic; xing_magic = mad_bit_read (&ptr, 4*8); /* Xing or Info */ if (xing_magic != 0x58696e67 && xing_magic != 0x496e666f) { return NULL; } xing = g_new0 (xmms_xing_t, 1); g_return_val_if_fail (xing, NULL); xing->flags = mad_bit_read (&ptr, 32); if (xmms_xing_has_flag (xing, XMMS_XING_FRAMES)) xing->frames = mad_bit_read (&ptr, 32); if (xmms_xing_has_flag (xing, XMMS_XING_BYTES)) xing->bytes = mad_bit_read (&ptr, 32); if (xmms_xing_has_flag (xing, XMMS_XING_TOC)) { gint i; for (i = 0; i < 100; i++) xing->toc[i] = mad_bit_read (&ptr, 8); } if (xmms_xing_has_flag (xing, XMMS_XING_SCALE)) { /* just move the pointer forward */ mad_bit_read (&ptr, 32); } xing->lame = parse_lame (&ptr); /* if (strncmp ((gchar *)ptr.byte, "LAME", 4) == 0) { lame = g_new0 (xmms_xing_lame_t, 1); XMMS_DBG ("Parsing LAME tag"); mad_bit_skip (&ptr, 4 * 8); mad_bit_nextbyte (&ptr); mad_bit_skip (&ptr, (8 * 5) + 12); lame->peak_amplitude = mad_bit_read (&ptr, 32); lame->radio_gain = mad_bit_read (&ptr, 16); lame->audiophile_gain = mad_bit_read (&ptr, 16); mad_bit_skip (&ptr, 16); lame->encoder_delay_start = mad_bit_read (&ptr, 12); lame->encoder_delay_stop = mad_bit_read (&ptr, 12); mad_bit_skip (&ptr, 8); lame->mp3_gain = mad_bit_read (&ptr, 8); xing->lame = lame; } */ if (xmms_xing_has_flag (xing, XMMS_XING_FRAMES) && xing->frames == 0) { xmms_log_info ("Corrupt xing header (frames == 0), ignoring"); xmms_xing_free (xing); return NULL; } if (xmms_xing_has_flag (xing, XMMS_XING_BYTES) && xing->bytes == 0) { xmms_log_info ("Corrupt xing header (bytes == 0), ignoring"); xmms_xing_free (xing); return NULL; } if (xmms_xing_has_flag (xing, XMMS_XING_TOC)) { gint i; for (i = 0; i < 99; i++) { if (xing->toc[i] > xing->toc[i + 1]) { xmms_log_info ("Corrupt xing header (toc not monotonic), ignoring"); xmms_xing_free (xing); return NULL; } } } return xing; }
/* * NAME: tag->parse() * DESCRIPTION: parse Xing/LAME tag(s) */ int tag_parse(struct tag *tag, struct mad_stream const *stream) { struct mad_bitptr ptr = stream->anc_ptr; struct mad_bitptr start = ptr; unsigned int bitlen = stream->anc_bitlen; unsigned long magic; int i; if (bitlen < 32) return -1; magic = mad_bit_read(&ptr, 32); bitlen -= 32; if (magic != XING_MAGIC && magic != INFO_MAGIC && magic != LAME_MAGIC) { /* * Due to an unfortunate historical accident, a Xing VBR tag may be * misplaced in a stream with CRC protection. We check for this by * assuming the tag began two octets prior and the high bits of the * following flags field are always zero. */ if (magic != ((XING_MAGIC << 16) & 0xffffffffL) && magic != ((INFO_MAGIC << 16) & 0xffffffffL)) return -1; magic >>= 16; /* backtrack the bit pointer */ ptr = start; mad_bit_skip(&ptr, 16); bitlen += 16; } if ((magic & 0x0000ffffL) == (XING_MAGIC & 0x0000ffffL)) tag->flags |= TAG_VBR; /* Xing tag */ if (magic == LAME_MAGIC) { ptr = start; bitlen += 32; } else if (parse_xing(&tag->xing, &ptr, &bitlen) == 0) tag->flags |= TAG_XING; /* encoder string */ if (bitlen >= 20 * 8) { start = ptr; for (i = 0; i < 20; ++i) { tag->encoder[i] = mad_bit_read(&ptr, 8); if (tag->encoder[i] == 0) break; /* keep only printable ASCII chars */ if (tag->encoder[i] < 0x20 || tag->encoder[i] >= 0x7f) { tag->encoder[i] = 0; break; } } tag->encoder[20] = 0; ptr = start; } /* LAME tag */ if (stream->next_frame - stream->this_frame >= 192 && parse_lame(&tag->lame, &ptr, &bitlen, crc_compute(stream->this_frame, 190, 0x0000)) == 0) { tag->flags |= TAG_LAME; tag->encoder[9] = 0; } else { for (i = 0; i < 20; ++i) { if (tag->encoder[i] == 0) break; /* stop at padding chars */ if (tag->encoder[i] == 0x55) { tag->encoder[i] = 0; break; } } } return 0; }