/**
 * Compresses video frame with tiles API
 *
 * @param[in]     s             compress state
 * @param[in]     frame         uncompressed frame
 * @param         buffer_index  0 or 1 - driver should have 2 output buffers, filling the selected one.
 *                Returned video frame should stay valid until requesting compress with the
 *                same index.
 * @param         parent        parent module (for the case when there is a need to reconfigure)
 * @return                      compressed video frame, may be NULL if compression failed
 */
static struct video_frame *compress_frame_tiles(struct compress_state_real *s, struct video_frame *frame,
        int buffer_index, struct module *parent)
{
    if(frame->tile_count != s->state_count) {
        s->state = realloc(s->state, frame->tile_count * sizeof(struct module *));
        for(unsigned int i = s->state_count; i < frame->tile_count; ++i) {
            char compress_options[1024];
            strncpy(compress_options, s->compress_options, sizeof(compress_options));
            compress_options[sizeof(compress_options) - 1] = '\0';
            s->state[i] = s->handle->init_func(parent, compress_options);
            if(!s->state[i]) {
                fprintf(stderr, "Compression initialization failed\n");
                return NULL;
            }
        }
        for(int i = 0; i < 2; ++i) {
            vf_free(s->out_frame[i]);
            s->out_frame[i] = vf_alloc(frame->tile_count);
        }
        s->state_count = frame->tile_count;
    }

    task_result_handle_t task_handle[frame->tile_count];

    struct compress_worker_data data_tile[frame->tile_count];
    for(unsigned int i = 0; i < frame->tile_count; ++i) {
        struct compress_worker_data *data = &data_tile[i];
        data->state = s->state[i];
        data->tile = &frame->tiles[i];
        data->desc = video_desc_from_frame(frame);
        data->desc.tile_count = 1;
        data->buffer_index = buffer_index;;
        data->callback = s->handle->compress_tile_func;

        task_handle[i] = task_run_async(compress_tile_callback, data);
    }

    for(unsigned int i = 0; i < frame->tile_count; ++i) {
        struct compress_worker_data *data = wait_task(task_handle[i]);

        if(i == 0) { // update metadata from first tile
            data->desc.tile_count = frame->tile_count;
            vf_write_desc(s->out_frame[buffer_index], data->desc);
        }

        if(data->ret) {
            memcpy(&s->out_frame[buffer_index]->tiles[i], data->ret, sizeof(struct tile));
        } else {
            return NULL;
        }
    }

    return s->out_frame[buffer_index];
}
Exemple #2
0
static struct video_frame *filter(void *, struct video_frame *in)
{
        if (in->color_spec != UYVY) {
                log_msg(LOG_LEVEL_WARNING, "Only supporte colorspace for mirror is currently UYVY!\n");
                return in;
        }

        struct video_frame *out = vf_alloc_desc_data(video_desc_from_frame(in));
        out->dispose = vf_free;

        unsigned char *in_data = (unsigned char *) in->tiles[0].data;
        unsigned char *out_data = (unsigned char *) out->tiles[0].data;

        int linesize = vc_get_linesize(in->tiles[0].width, in->color_spec);
        for (unsigned int y = 0; y < in->tiles[0].height; ++y) {
                mirror_line_UYVY(out_data + y * linesize, in_data + y * linesize, linesize);
        }

        VIDEO_FRAME_DISPOSE(in);

        return out;
}
Exemple #3
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;
}
Exemple #4
0
struct video_frame * jpeg_compress(struct module *mod, struct video_frame * tx, int buffer_idx)
{
        struct state_video_compress_jpeg *s = (struct state_video_compress_jpeg *) mod->priv_data;
        int i;
        unsigned char *line1, *line2;
        struct video_frame *out;

        unsigned int x;

        cudaSetDevice(cuda_devices[0]);
        
        if(!s->encoder) {
                int ret;
                ret = configure_with(s, tx);
                if(!ret) {
                        return NULL;
                }
        }

        struct video_desc desc;
        desc = video_desc_from_frame(tx);

        // if format changed, reconfigure
        if(!video_desc_eq_excl_param(s->saved_desc, desc, PARAM_INTERLACING)) {
                cleanup_state(s);
                int ret;
                ret = configure_with(s, tx);
                if(!ret) {
                        return NULL;
                }
        }

        out = s->out[buffer_idx];

        for (x = 0; x < tx->tile_count;  ++x) {
                struct tile *in_tile = vf_get_tile(tx, x);
                struct tile *out_tile = vf_get_tile(out, x);
                
                line1 = (unsigned char *) in_tile->data;
                line2 = (unsigned char *) s->decoded;
                
                for (i = 0; i < (int) in_tile->height; ++i) {
                        s->decoder(line2, line1, s->encoder_input_linesize,
                                        0, 8, 16);
                        line1 += vc_get_linesize(in_tile->width, tx->color_spec);
                        line2 += s->encoder_input_linesize;
                }
                
                line1 = (unsigned char *) out_tile->data + (in_tile->height - 1) * s->encoder_input_linesize;
                for( ; i < (int) out->tiles[0].height; ++i) {
                        memcpy(line2, line1, s->encoder_input_linesize);
                        line2 += s->encoder_input_linesize;
                }
                
                /*if(s->interlaced_input)
                        vc_deinterlace((unsigned char *) s->decoded, s->encoder_input_linesize,
                                        s->out->tiles[0].height);*/
                
                uint8_t *compressed;
                int size;
                int ret;


                struct gpujpeg_encoder_input encoder_input;
                gpujpeg_encoder_input_set_image(&encoder_input, (uint8_t *) s->decoded);
                ret = gpujpeg_encoder_encode(s->encoder, &encoder_input, &compressed, &size);
                
                if(ret != 0)
                        return NULL;
                
                out_tile->data_len = size;
                memcpy(out_tile->data, compressed, size);
        }
        
        return out;
}