Beispiel #1
0
static void compress_thread(void *args)
{
        struct video_compress *compress = (struct video_compress *)args;
        int myId, range, my_range, x;
        int my_height;
        unsigned char *retv;

        pthread_mutex_lock(&(compress->lock));
        myId = compress->thread_count;
        compress->thread_count++;
        pthread_mutex_unlock(&(compress->lock));

        fprintf(stderr, "Compress thread %d online.\n", myId);

        while (1) {
                platform_sem_wait(&compress->thread_compress[myId]);
                if(fastdxt_should_exit) break;

                my_height = (compress->tile[compress->buffer_idx]->height / compress->num_threads) / 4 * 4;
                range = my_height * compress->tile[compress->buffer_idx]->width; /* for all threads except the last */

                if(myId == compress->num_threads - 1) {
                        my_height = compress->tile[compress->buffer_idx]->height - my_height /* "their height" */ * myId;
                }
                my_range = my_height * compress->tile[compress->buffer_idx]->width;

                if(!compress->rgb)
                {
                        unsigned char *input;
                        input = (compress->output_data) + myId
                                * range * 2;
                        retv = compress->buffer[myId];
                        /* Repack the data to YUV 4:4:4 Format */
                        for (x = 0; x < my_range; x += 2) {
                                retv[4 * x] = input[2 * x + 1]; //Y1
                                retv[4 * x + 1] = input[2 * x]; //U1
                                retv[4 * x + 2] = input[2 * x + 2];     //V1
                                retv[4 * x + 3] = 255;  //Alpha

                                retv[4 * x + 4] = input[2 * x + 3];     //Y2
                                retv[4 * x + 5] = input[2 * x]; //U1
                                retv[4 * x + 6] = input[2 * x + 2];     //V1
                                retv[4 * x + 7] = 255;  //Alpha
                        }
                } else {
                        retv = (compress->output_data) + myId * range * 4;
                }

                DirectDXT1(retv,
                               ((unsigned char *) compress->tile[compress->buffer_idx]->data) + myId * range / 2,
                               compress->tile[compress->buffer_idx]->width, my_height);

                platform_sem_post(&compress->thread_done[myId]);
        }
        
        platform_sem_post(&compress->thread_done[myId]);
}
Beispiel #2
0
void video_export_destroy(struct video_export *s)
{
        if(s) {
                // poison
                struct output_entry *entry = calloc(sizeof(struct output_entry), 1);

                pthread_mutex_lock(&s->lock);
                {
                        if(s->head) {
                                s->tail->next = entry;
                                s->tail = entry;
                        } else {
                                s->head = s->tail = entry;
                        }
                }
                pthread_mutex_unlock(&s->lock);
                platform_sem_post(&s->semaphore);

                pthread_join(s->thread_id, NULL);
                pthread_mutex_destroy(&s->lock);

                // write summary
                if(s->total > 0) {
                        output_summary(s);
                }

                free(s);
        }
}
Beispiel #3
0
void fastdxt_done(void *args)
{
        struct video_compress *compress = (struct video_compress *)args;
        int x;
        
        pthread_mutex_lock(&(compress->lock)); /* wait for fastdxt_compress if running */
        fastdxt_should_exit = TRUE;
        
        for (x = 0; x < compress->num_threads; x++) {
                platform_sem_post(&compress->thread_compress[x]);
        }

        for (x = 0; x < compress->num_threads; x++) {
                platform_sem_wait(&compress->thread_done[x]);
        }

        pthread_mutex_unlock(&(compress->lock));
        
        pthread_mutex_destroy(&(compress->lock));
        
        for (x = 0; x < compress->num_threads; ++x)
                free(compress->buffer[x]);
        free(compress);
                
        
}
Beispiel #4
0
void video_export(struct video_export *s, struct video_frame *frame)
{
        if(!s) {
                return;
        }

        assert(frame != NULL);

        if(s->saved_desc.width == 0) {
                s->saved_desc = video_desc_from_frame(frame);
        } else {
                if(!video_desc_eq(s->saved_desc, video_desc_from_frame(frame))) {
                        fprintf(stderr, "[Video export] Format change detected, not exporting.\n");
                        return;
                }
        }

        for (unsigned int i = 0; i < frame->tile_count; ++i) {
                assert(frame->tiles[i].data != NULL && frame->tiles[i].data_len != 0);

                struct output_entry *entry = malloc(sizeof(struct output_entry));

                entry->data_len = frame->tiles[i].data_len;
                entry->data = (char *) malloc(entry->data_len);
                entry->filename = malloc(512);
                entry->next = NULL;

                if(frame->tile_count == 1) {
                        snprintf(entry->filename, 512, "%s/%08d.%s", s->path, s->total + 1, get_codec_file_extension(frame->color_spec));
                } else {
                        // add also tile index
                        snprintf(entry->filename, 512, "%s/%08d_%d.%s", s->path, s->total + 1, i, get_codec_file_extension(frame->color_spec));
                }
                memcpy(entry->data, frame->tiles[i].data, entry->data_len);

                pthread_mutex_lock(&s->lock);
                {
                        // check if we do not occupy too much memory
                        if(s->queue_len >= MAX_QUEUE_SIZE) {
                                fprintf(stderr, "[Video export] Maximal queue size (%d) exceeded, not saving frame %d.\n",
                                                MAX_QUEUE_SIZE,
                                                s->total++); // we increment total size to keep the index
                                pthread_mutex_unlock(&s->lock);
                                free(entry->data);
                                free(entry);
                                return;
                        }

                        if(s->head) {
                                s->tail->next = entry;
                                s->tail = entry;
                        } else {
                                s->head = s->tail = entry;
                        }
                        s->queue_len += 1;
                }
                pthread_mutex_unlock(&s->lock);

                platform_sem_post(&s->semaphore);
        }

        s->total += 1;
}
Beispiel #5
0
struct video_frame * fastdxt_compress(void *args, struct video_frame *tx, int buffer_idx)
{
        /* This thread will be called from main.c and handle the compress_threads */
        struct video_compress *compress = (struct video_compress *)args;
        unsigned int x;
        unsigned char *line1, *line2;
        struct video_frame *out = compress->out[buffer_idx];
        struct tile *out_tile = &out->tiles[0];

        assert(tx->tile_count == 1);
        assert(vf_get_tile(tx, 0)->width % 4 == 0);
        
        pthread_mutex_lock(&(compress->lock));

        if(vf_get_tile(tx, 0)->width != out_tile->width ||
                        vf_get_tile(tx, 0)->height != out_tile->height ||
                        tx->interlacing != compress->interlacing_source ||
                        tx->color_spec != compress->tx_color_spec)
        {
                int ret;
                ret = reconfigure_compress(compress, vf_get_tile(tx, 0)->width, vf_get_tile(tx, 0)->height, tx->color_spec, tx->interlacing, tx->fps);
                if(!ret)
                        return NULL;
        }

        line1 = (unsigned char *) tx->tiles[0].data;
        line2 = compress->output_data;

        for (x = 0; x < out_tile->height; ++x) {
                int src_linesize = vc_get_linesize(out_tile->width, compress->tx_color_spec);
                compress->decoder(line2, line1, out_tile->linesize,
                                0, 8, 16);
                line1 += src_linesize;
                line2 += out_tile->linesize;
        }

        if(tx->interlacing != INTERLACED_MERGED && tx->interlacing != PROGRESSIVE) {
                fprintf(stderr, "Unsupported interlacing format.\n");
                exit_uv(1);
        }

        if(tx->interlacing == INTERLACED_MERGED) {
                vc_deinterlace(compress->output_data, out_tile->linesize,
                                out_tile->height);
        }

        compress->buffer_idx = buffer_idx;

        for (x = 0; x < (unsigned int) compress->num_threads; x++) {
                platform_sem_post(&compress->thread_compress[x]);
        }

        for (x = 0; x < (unsigned int) compress->num_threads; x++) {
                platform_sem_wait(&compress->thread_done[x]);
        }

        out_tile->data_len = out_tile->width * compress->dxt_height / 2;
        
        pthread_mutex_unlock(&(compress->lock));

        return out;
}