示例#1
0
int
id3tag_write_v1(lame_global_flags * gfp)
{
    lame_internal_flags *const gfc = gfp->internal_flags;
    size_t  i, n, m;
    unsigned char tag[128];

    m = sizeof(tag);
    n = lame_get_id3v1_tag(gfp, tag, m);
    if (n > m) {
        return 0;
    }
    /* write tag directly into bitstream at current position */
    for (i = 0; i < n; ++i) {
        add_dummy_byte(gfc, tag[i], 1);
    }
    return (int) n;     /* ok, tag has fixed size of 128 bytes, well below 2GB */
}
示例#2
0
int
id3tag_write_v2(lame_global_flags * gfp)
{
    lame_internal_flags *gfc = gfp->internal_flags;
#if 0
    debug_tag_spec_flags(gfc, "write v2");
#endif
    if (test_tag_spec_flags(gfc, V1_ONLY_FLAG)) {
        return 0;
    }
    if (test_tag_spec_flags(gfc, CHANGED_FLAG)) {
        unsigned char *tag = 0;
        size_t  tag_size, n;

        n = lame_get_id3v2_tag(gfp, 0, 0);
        tag = malloc(n);
        if (tag == 0) {
            return -1;
        }
        tag_size = lame_get_id3v2_tag(gfp, tag, n);
        if (tag_size > n) {
            free(tag);
            return -1;
        }
        else {
            size_t  i;
            /* write tag directly into bitstream at current position */
            for (i = 0; i < tag_size; ++i) {
                add_dummy_byte(gfc, tag[i], 1);
            }
        }
        free(tag);
        return (int) tag_size; /* ok, tag should not exceed 2GB */
    }
    return 0;
}
示例#3
0
int
id3tag_write_v2(lame_global_flags *gfp)
{
    lame_internal_flags *gfc = gfp->internal_flags;
    if ((gfc->tag_spec.flags & CHANGED_FLAG)
            && !(gfc->tag_spec.flags & V1_ONLY_FLAG)) {
        /* calculate length of four fields which may not fit in verion 1 tag */
        size_t title_length = gfc->tag_spec.title
            ? strlen(gfc->tag_spec.title) : 0;
        size_t artist_length = gfc->tag_spec.artist
            ? strlen(gfc->tag_spec.artist) : 0;
        size_t album_length = gfc->tag_spec.album
            ? strlen(gfc->tag_spec.album) : 0;
        size_t comment_length = gfc->tag_spec.comment
            ? strlen(gfc->tag_spec.comment) : 0;
        /* write tag if explicitly requested or if fields overflow */
        if ((gfc->tag_spec.flags & (ADD_V2_FLAG | V2_ONLY_FLAG))
                || (title_length > 30)
                || (artist_length > 30) || (album_length > 30)
                || (comment_length > 30)
                || (gfc->tag_spec.track && (comment_length > 28))) {
            size_t tag_size;
            char year[5];
            size_t year_length;
            char track[3];
            size_t track_length;
            char genre[6];
            size_t genre_length;
            unsigned char *tag;
            unsigned char *p;
            size_t adjusted_tag_size;
            unsigned int index;
            /* calulate size of tag starting with 10-byte tag header */
            tag_size = 10;
            if (title_length) {
                /* add 10-byte frame header, 1 encoding descriptor byte ... */
                tag_size += 11 + title_length;
            }
            if (artist_length) {
                tag_size += 11 + artist_length;
            }
            if (album_length) {
                tag_size += 11 + album_length;
            }
            if (gfc->tag_spec.year) {
                year_length = sprintf(year, "%d", gfc->tag_spec.year);
                tag_size += 11 + year_length;
            } else {
                year_length = 0;
            }
            if (comment_length) {
                /* add 10-byte frame header, 1 encoding descriptor byte,
                 * 3-byte language descriptor, 1 content descriptor byte ... */
                tag_size += 15 + comment_length;
            }
            if (gfc->tag_spec.track) {
                track_length = sprintf(track, "%d", gfc->tag_spec.track);
                tag_size += 11 + track_length;
            } else {
                track_length = 0;
            }
            if (gfc->tag_spec.genre != GENRE_NUM_UNKNOWN) {
                genre_length = sprintf(genre, "(%d)", gfc->tag_spec.genre);
                tag_size += 11 + genre_length;
            } else {
                genre_length = 0;
            }
            if (gfc->tag_spec.flags & PAD_V2_FLAG) {
                /* add 128 bytes of padding */
                tag_size += 128;
            }
            tag = (unsigned char *)malloc(tag_size);
            if (!tag) {
                return -1;
            }
            p = tag;
            /* set tag header starting with file identifier */
            *p++ = 'I'; *p++ = 'D'; *p++ = '3';
            /* set version number word */
            *p++ = 3; *p++ = 0;
            /* clear flags byte */
            *p++ = 0;
            /* calculate and set tag size = total size - header size */
            adjusted_tag_size = tag_size - 10;
            /* encode adjusted size into four bytes where most significant
             * bit is clear in each byte, for 28-bit total */
            *p++ = (adjusted_tag_size >> 21) & 0x7fu;
            *p++ = (adjusted_tag_size >> 14) & 0x7fu;
            *p++ = (adjusted_tag_size >> 7) & 0x7fu;
            *p++ = adjusted_tag_size & 0x7fu;

            /*
             * NOTE: The remainder of the tag (frames and padding, if any)
             * are not "unsynchronized" to prevent false MPEG audio headers
             * from appearing in the bitstream.  Why?  Well, most players
             * and utilities know how to skip the ID3 version 2 tag by now
             * even if they don't read its contents, and it's actually
             * very unlikely that such a false "sync" pattern would occur
             * in just the simple text frames added here.
             */

            /* set each frame in tag */
            p = set_frame(p, TITLE_FRAME_ID, gfc->tag_spec.title, title_length);
            p = set_frame(p, ARTIST_FRAME_ID, gfc->tag_spec.artist,
                    artist_length);
            p = set_frame(p, ALBUM_FRAME_ID, gfc->tag_spec.album, album_length);
            p = set_frame(p, YEAR_FRAME_ID, year, year_length);
            p = set_frame(p, COMMENT_FRAME_ID, gfc->tag_spec.comment,
                    comment_length);
            p = set_frame(p, TRACK_FRAME_ID, track, track_length);
            p = set_frame(p, GENRE_FRAME_ID, genre, genre_length);
            /* clear any padding bytes */
            memset(p, 0, tag_size - (p - tag));
            /* write tag directly into bitstream at current position */
            for (index = 0; index < tag_size; ++index) {
                add_dummy_byte(gfp, tag[index]);
            }
            free(tag);
            return tag_size;
        }