Exemple #1
0
int main (int argc, char** argv)
{
    flvtag_t tag;
    FILE* flv = flv_open_read (argv[1]);
    FILE* out = flv_open_write (argv[3]);

    int has_audio, has_video;
    flvtag_init (&tag);

    if (!flv_read_header (flv,&has_audio,&has_video)) {
        fprintf (stderr,"%s is not an flv file\n", argv[1]);
        return EXIT_FAILURE;
    }

    srt_t* head = srt_from_file (argv[2]);
    srt_t* srt = head;

    if (! head) {
        fprintf (stderr,"%s is not an srt file\n", argv[2]);
        return EXIT_FAILURE;
    }

    flv_write_header (out,has_audio,has_video);

    while (flv_read_tag (flv,&tag)) {
        // TODO handle B freame!
        if (srt && flvtag_pts_seconds (&tag) >= srt->timestamp && flvtag_avcpackettype_nalu == flvtag_avcpackettype (&tag)) {
            fprintf (stderr,"%f: %s\n", srt->timestamp, srt_data (srt));
            flvtag_addcaption (&tag, srt_data (srt));
            srt = srt->next;
        }

        flv_write_tag (out,&tag);
        // Write tag out here
    }

    srt_free (head);
    return EXIT_SUCCESS;
}
Exemple #2
0
int main(int argc, char * argv[])
{


	int i,ret;

	av_register_all();

	nb_files = argc - 1;

	durations = calloc(nb_files,sizeof( uint64_t ));
	datasizes = calloc(nb_files,sizeof( double ));
	nb_keyframes = calloc(nb_files,sizeof( double ));

	keyframes = calloc(nb_files, sizeof(AVIndexEntry*));


	// read metadata of the first package.
	// we only need to write keyframes, duration , videorate , audiorate , width , height and creator:)

	//解析第一个文件

	for (i = 0; i < 1; i++)
	{
		int k;

		AVFormatContext  * flv=NULL;

		char * filename;

		filename = argv[i+1];

		avformat_open_input(&flv,filename,NULL,NULL);

		av_find_stream_info(flv);

		hasAudio = strcmp(av_dict_get(flv->metadata,"hasAudio",NULL,0)->value,"true")==0;
		hasVideo = strcmp(av_dict_get(flv->metadata,"hasVideo",NULL,0)->value,"true")==0;
		stereo = strcmp(av_dict_get(flv->metadata,"stereo",NULL,0)->value,"true")==0;

		durations[i] = flv->duration;

		duration += durations[i];

		width = strtod(av_dict_get(flv->metadata,"width",NULL,0)->value,NULL);
		height = strtod(av_dict_get(flv->metadata,"height",NULL,0)->value,NULL);
		audiosamplerate = strtod(av_dict_get(flv->metadata,"audiosamplerate",NULL,0)->value,NULL);
		audiosamplesize = strtod(av_dict_get(flv->metadata,"audiosamplesize",NULL,0)->value,NULL);

		audiocodecid = strtod(av_dict_get(flv->metadata,"audiocodecid",NULL,0)->value,NULL);
		videocodecid = strtod(av_dict_get(flv->metadata,"videocodecid",NULL,0)->value,NULL);

		videodatarate = strtod(av_dict_get(flv->metadata,"videodatarate",NULL,0)->value,NULL);
		audiodatarate = strtod(av_dict_get(flv->metadata,"audiodatarate",NULL,0)->value,NULL);

		//获得 keyframes position

		nb_keyframes[i] =  flv->streams[0]->nb_index_entries;
		nb_keyframes_all += nb_keyframes[i];

		keyframes[i] = calloc(nb_keyframes[i],sizeof(AVIndexEntry));

		for(k = 0 ; k < nb_keyframes[i]; k++)
		{
			keyframes[i][k] =  flv->streams[0]->index_entries[k];
			keyframes[i][k].pos -=  flv->streams[0]->index_entries[0].pos;
		}

		datasizes[i] = strtod(av_dict_get(flv->metadata,"datasize",NULL,0)->value,NULL);

		avformat_free_context(flv);

	}

	for (i = 1; i < nb_files ; i++)
	{
		int k;

		AVFormatContext  * flv=NULL;

		char * filename;

		filename = argv[i+1];

		avformat_open_input(&flv,filename,NULL,NULL);

		av_find_stream_info(flv);

		durations[i] = flv->duration;

		duration += durations[i];

		//获得 keyframes position

		keyframes[i] = calloc(nb_keyframes[i],sizeof(AVIndexEntry));
		nb_keyframes_all += nb_keyframes[i];

		for(k = 0 ; k < nb_keyframes[i]; k++)
		{
			keyframes[i][k] =  flv->streams[0]->index_entries[k];
			keyframes[i][k].pos -=  flv->streams[0]->index_entries[0].pos;
		}

		datasizes[i] = strtod(av_dict_get(flv->metadata,"datasize",NULL,0)->value,NULL) - flv->streams[0]->index_entries->pos ;

		avformat_free_context(flv);

	}

	//正常的开始写 flv 文件 吧

	out = fopen("out.flv","w");

	flv_write_header();

	flv_write_metadata();

	uint64_t timestamp;
	uint32_t lastsize;

	for (lastsize = 0,i = 0 ,timestamp = 0; i < argc - 1; timestamp += durations[i],i++ )
	{
		char * filename;

		filename = argv[i+1];

		FILE * in = fopen(filename,"r");
		lastsize = flv_merge_stream(in,out,timestamp,lastsize);
	}

	fclose(out);

	return EXIT_SUCCESS;
}
Exemple #3
0
/*
    Write the flv output file
*/
static int write_flv(flv_stream * flv_in, FILE * flv_out, const flv_info * info, const flv_metadata * meta, const flvmeta_opts * opts) {
    uint32_be size;
    uint32 on_metadata_name_size;
    uint32 on_metadata_size;
    uint32 prev_timestamp_video;
    uint32 prev_timestamp_audio;
    uint32 prev_timestamp_meta;
    uint8 timestamp_extended_video;
    uint8 timestamp_extended_audio;
    uint8 timestamp_extended_meta;
    byte * copy_buffer;
    flv_tag ft, omft;
    int have_on_last_second;

    if (opts->verbose) {
        fprintf(stdout, "Writing %s...\n", opts->output_file);
    }

    /* write the flv header */
    if (flv_write_header(flv_out, &info->header) != 1) {
        return ERROR_WRITE;
    }

    /* first "previous tag size" */
    size = swap_uint32(0);
    if (fwrite(&size, sizeof(uint32_be), 1, flv_out) != 1) {
        return ERROR_WRITE;
    }

    /* create the onMetaData tag */
    on_metadata_name_size = (uint32)amf_data_size(meta->on_metadata_name);
    on_metadata_size = (uint32)amf_data_size(meta->on_metadata);

    omft.type = FLV_TAG_TYPE_META;
    omft.body_length = uint32_to_uint24_be(on_metadata_name_size + on_metadata_size);
    flv_tag_set_timestamp(&omft, 0);
    omft.stream_id = uint32_to_uint24_be(0);
    
    /* write the computed onMetaData tag first if it doesn't exist in the input file */
    if (info->on_metadata_size == 0) {
        if (flv_write_tag(flv_out, &omft) != 1
        || amf_data_file_write(meta->on_metadata_name, flv_out) < on_metadata_name_size
        || amf_data_file_write(meta->on_metadata, flv_out) < on_metadata_size) {
            return ERROR_WRITE;
        }

        /* previous tag size */
        size = swap_uint32(FLV_TAG_SIZE + on_metadata_name_size + on_metadata_size);
        if (fwrite(&size, sizeof(uint32_be), 1, flv_out) != 1) {
            return ERROR_WRITE;
        }
    }

    /* extended timestamp initialization */
    prev_timestamp_video = 0;
    prev_timestamp_audio = 0;
    prev_timestamp_meta = 0;
    timestamp_extended_video = 0;
    timestamp_extended_audio = 0;
    timestamp_extended_meta = 0;

    /* copy the tags verbatim */
    flv_reset(flv_in);

    copy_buffer = (byte *)malloc(info->biggest_tag_body_size + FLV_TAG_SIZE);
    have_on_last_second = 0;
    while (flv_read_tag(flv_in, &ft) == FLV_OK) {
        file_offset_t offset;
        uint32 body_length;
        uint32 timestamp;

        offset = flv_get_current_tag_offset(flv_in);
        body_length = flv_tag_get_body_length(ft);
        timestamp = flv_tag_get_timestamp(ft);

        /* extended timestamp fixing */
        if (ft.type == FLV_TAG_TYPE_META) {
            if (timestamp < prev_timestamp_meta
            && prev_timestamp_meta - timestamp > 0xF00000) {
                ++timestamp_extended_meta;
            }
            prev_timestamp_meta = timestamp;
            if (timestamp_extended_meta > 0) {
                timestamp += timestamp_extended_meta << 24;
            }
        }
        else if (ft.type == FLV_TAG_TYPE_AUDIO) {
            if (timestamp < prev_timestamp_audio
            && prev_timestamp_audio - timestamp > 0xF00000) {
                ++timestamp_extended_audio;
            }
            prev_timestamp_audio = timestamp;
            if (timestamp_extended_audio > 0) {
                timestamp += timestamp_extended_audio << 24;
            }
        }
        else if (ft.type == FLV_TAG_TYPE_VIDEO) {
            if (timestamp < prev_timestamp_video
            && prev_timestamp_video - timestamp > 0xF00000) {
                ++timestamp_extended_video;
            }
            prev_timestamp_video = timestamp;
            if (timestamp_extended_video > 0) {
                timestamp += timestamp_extended_video << 24;
            }
        }

        /* non-zero starting timestamp handling */
        if (opts->reset_timestamps && timestamp > 0) {
            timestamp -= info->first_timestamp;
        }

        flv_tag_set_timestamp(&ft, timestamp);

        /* if we're at the offset of the first onMetaData tag in the input file,
           we write the one we computed instead, discarding the old one */
        if (info->on_metadata_offset == offset) {
            if (flv_write_tag(flv_out, &omft) != 1
            || amf_data_file_write(meta->on_metadata_name, flv_out) < on_metadata_name_size
            || amf_data_file_write(meta->on_metadata, flv_out) < on_metadata_size) {
                free(copy_buffer);
                return ERROR_WRITE;
            }

            /* previous tag size */
            size = swap_uint32(FLV_TAG_SIZE + on_metadata_name_size + on_metadata_size);
            if (fwrite(&size, sizeof(uint32_be), 1, flv_out) != 1) {
                free(copy_buffer);
                return ERROR_WRITE;
            }
        }
        else {
            size_t read_body;
            
            /* insert an onLastSecond metadata tag */
            if (opts->insert_onlastsecond && !have_on_last_second && !info->have_on_last_second && (info->last_timestamp - timestamp) <= 1000) {
                flv_tag tag;
                uint32 on_last_second_name_size = (uint32)amf_data_size(meta->on_last_second_name);
                uint32 on_last_second_size = (uint32)amf_data_size(meta->on_last_second);
                tag.type = FLV_TAG_TYPE_META;
                tag.body_length = uint32_to_uint24_be(on_last_second_name_size + on_last_second_size);
                tag.timestamp = ft.timestamp;
                tag.timestamp_extended = ft.timestamp_extended;
                tag.stream_id = uint32_to_uint24_be(0);
                if (flv_write_tag(flv_out, &tag) != 1
                || amf_data_file_write(meta->on_last_second_name, flv_out) < on_last_second_name_size
                || amf_data_file_write(meta->on_last_second, flv_out) < on_last_second_size) {
                    free(copy_buffer);
                    return ERROR_WRITE;
                }

                /* previous tag size */
                size = swap_uint32(FLV_TAG_SIZE + on_last_second_name_size + on_last_second_size);
                if (fwrite(&size, sizeof(uint32_be), 1, flv_out) != 1) {
                    free(copy_buffer);
                    return ERROR_WRITE;
                }

                have_on_last_second = 1;
            }

            /* if the tag is bigger than expected, it means that
               it's an unknown tag type. In this case, we only
               copy as much data as the copy buffer can contain */
            if (body_length > info->biggest_tag_body_size) {
                body_length = info->biggest_tag_body_size;
            }

            /* copy the tag verbatim */
            read_body = flv_read_tag_body(flv_in, copy_buffer, body_length);
            if (read_body < body_length) {
                /* we have reached end of file on an incomplete tag */
                if (opts->error_handling == FLVMETA_EXIT_ON_ERROR) {
                    free(copy_buffer);
                    return ERROR_EOF;
                }
                else if (opts->error_handling == FLVMETA_FIX_ERRORS) {
                    /* the tag is bogus, just omit it,
                       even though it will make the whole file length
                       calculation wrong, and the metadata inaccurate */
                    /* TODO : fix it by handling that problem in the first pass */
                    free(copy_buffer);
                    return OK;
                }
                else if (opts->error_handling == FLVMETA_IGNORE_ERRORS) {
                    /* just copy the whole tag and exit */
                    flv_write_tag(flv_out, &ft);
                    fwrite(copy_buffer, 1, read_body, flv_out);
                    free(copy_buffer);
                    size = swap_uint32(FLV_TAG_SIZE + read_body);
                    fwrite(&size, sizeof(uint32_be), 1, flv_out);
                    return OK;
                }
            }
            if (flv_write_tag(flv_out, &ft) != 1
            || fwrite(copy_buffer, 1, body_length, flv_out) < body_length) {
                free(copy_buffer);
                return ERROR_WRITE;
            }

            /* previous tag length */
            size = swap_uint32(FLV_TAG_SIZE + body_length);
            if (fwrite(&size, sizeof(uint32_be), 1, flv_out) != 1) {
                free(copy_buffer);
                return ERROR_WRITE;
            }
        }        
    }

    if (opts->verbose) {
        fprintf(stdout, "%s successfully written\n", opts->output_file);
    }

    free(copy_buffer);
    return OK;
}
Exemple #4
0
int main(int argc, char** argv)
{
    flvtag_t tag;
    srt_t* old_srt = NULL;
    srt_cue_t* next_cue = NULL;
    double timestamp, offset = 0, clear_timestamp = 0;
    int has_audio, has_video;
    FILE* flv = flv_open_read(argv[1]);
    int fd = open(argv[2], O_RDWR);
    FILE* out = flv_open_write(argv[3]);

    flvtag_init(&tag);

    if (!flv_read_header(flv, &has_audio, &has_video)) {
        fprintf(stderr, "%s is not an flv file\n", argv[1]);
        return EXIT_FAILURE;
    }

    flv_write_header(out, has_audio, has_video);

    fprintf(stderr, "Reading flv from %s\n", argv[1]);
    fprintf(stderr, "Reading captons from %s\n", argv[2]);
    fprintf(stderr, "Writing flv to %s\n", argv[3]);

    while (flv_read_tag(flv, &tag)) {

        srt_t* cur_srt = srt_from_fd(fd);
        timestamp = flvtag_pts_seconds(&tag);

        if (cur_srt) {
            fprintf(stderr, "Loaded new SRT at time %f\n", timestamp);
            if (old_srt != NULL) {
                srt_free(old_srt);
            }
            old_srt = cur_srt;
            offset = timestamp;
            clear_timestamp = timestamp;
            next_cue = cur_srt->cue_head;
        }

        if (flvtag_avcpackettype_nalu == flvtag_avcpackettype(&tag)) {
            if (next_cue && (offset + next_cue->timestamp) <= timestamp) {
                fprintf(stderr, "T: %0.02f (%0.02fs):\n%s\n", (offset + next_cue->timestamp), next_cue->duration, srt_cue_data(next_cue));
                clear_timestamp = (offset + next_cue->timestamp) + next_cue->duration;
                flvtag_addcaption_text(&tag, srt_cue_data(next_cue));
                next_cue = next_cue->next;
            } else if (0 <= clear_timestamp && clear_timestamp <= timestamp) {
                fprintf(stderr, "T: %0.02f: [CAPTIONS CLEARED]\n", timestamp);
                flvtag_addcaption_text(&tag, NULL);
                clear_timestamp = -1;
            }
        }

        flv_write_tag(out, &tag);
    }

    srt_free(old_srt);
    flvtag_free(&tag);
    flv_close(flv);
    flv_close(out);
    return EXIT_SUCCESS;
}