예제 #1
0
static void
write_thumb(const AVCodecContext *src, const AVFrame *sframe, 
            int width, int height, const char *cacheid, time_t mtime)
{
  if(thumbcodec == NULL)
    return;

  AVCodecContext *ctx = thumbctx;

  if(ctx == NULL || ctx->width  != width || ctx->height != height) {
    
    if(ctx != NULL) {
      avcodec_close(ctx);
      free(ctx);
    }

    ctx = avcodec_alloc_context3(thumbcodec);
    ctx->pix_fmt = AV_PIX_FMT_YUVJ420P;
    ctx->time_base.den = 1;
    ctx->time_base.num = 1;
    ctx->sample_aspect_ratio.num = 1;
    ctx->sample_aspect_ratio.den = 1;
    ctx->width  = width;
    ctx->height = height;

    if(avcodec_open2(ctx, thumbcodec, NULL) < 0) {
      TRACE(TRACE_ERROR, "THUMB", "Unable to open thumb encoder");
      thumbctx = NULL;
      return;
    }
    thumbctx = ctx;
  }

  AVFrame *oframe = av_frame_alloc();

  avpicture_alloc((AVPicture *)oframe, ctx->pix_fmt, width, height);
      
  struct SwsContext *sws;
  sws = sws_getContext(src->width, src->height, src->pix_fmt,
                       width, height, ctx->pix_fmt, SWS_BILINEAR,
                       NULL, NULL, NULL);

  sws_scale(sws, (const uint8_t **)sframe->data, sframe->linesize,
            0, src->height, &oframe->data[0], &oframe->linesize[0]);
  sws_freeContext(sws);

  oframe->pts = AV_NOPTS_VALUE;
  AVPacket out;
  memset(&out, 0, sizeof(AVPacket));
  int got_packet;
  int r = avcodec_encode_video2(ctx, &out, oframe, &got_packet);
  if(r >= 0 && got_packet) {
    buf_t *b = buf_create_and_adopt(out.size, out.data, &av_free);
    blobcache_put(cacheid, "videothumb", b, INT32_MAX, NULL, mtime, 0);
    buf_release(b);
  } else {
    assert(out.data == NULL);
  }
  av_frame_free(&oframe);
}
예제 #2
0
JSBool
js_cache_put(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
  char stash[256];
  const char *key,*lstash;
  char *value;
  uint32_t len, maxage;
  JSObject *o;
  htsbuf_queue_t out;
  js_plugin_t *jsp = JS_GetPrivate(cx, obj);

  if (!JS_ConvertArguments(cx, argc, argv, "ssou",
			   &lstash, &key, &o, &maxage))
    return JS_FALSE;

  if (o == NULL) {
    JS_ReportError(cx, "Not an object");
    return JS_FALSE;
  }

  // json encode object
  htsbuf_queue_init(&out, 0);
  if (json_encode_from_object(cx, o, &out) != 0) {
    JS_ReportError(cx, "Not an JSON object");
    return JS_FALSE;
  }

  len = out.hq_size;
  value = JS_malloc(cx,len + 1);
  value[len] = '\0';
  htsbuf_read(&out, value, len);

  // put json encoded object onto cache
  snprintf(stash, sizeof(stash), "plugin/%s/%s", jsp->jsp_id, lstash);
  blobcache_put(key, stash, value, len, maxage, NULL, 0);

  return JS_TRUE;
}
예제 #3
0
static image_t *
thumb_from_attachment(const char *url, int64_t offset, int size,
                      char *errbuf, size_t errlen, const char *cacheid,
                      time_t mtime)
{
  fa_handle_t *fh = fa_open(url, errbuf, errlen);
  if(fh == NULL)
    return NULL;

  fh = fa_slice_open(fh, offset, size);
  buf_t *buf = fa_load_and_close(fh);
  if(buf == NULL) {
    snprintf(errbuf, errlen, "Load error");
    return NULL;
  }
  image_t *img = fa_imageloader_buf(buf, errbuf, errlen);

  if(img != NULL) {
    blobcache_put(cacheid, "videothumb", buf, INT32_MAX, NULL, mtime, 0);
  }

  buf_release(buf);
  return img;
}
예제 #4
0
static pixmap_t *
fa_image_from_video2(const char *url, const image_meta_t *im,
                     const char *cacheid, char *errbuf, size_t errlen,
                     int sec, time_t mtime)
{
    pixmap_t *pm = NULL;

    if(ifv_url == NULL || strcmp(url, ifv_url)) {
        // Need to open
        int i;
        AVFormatContext *fctx;
        fa_handle_t *fh = fa_open_ex(url, errbuf, errlen, FA_BUFFERED_BIG, NULL);

        if(fh == NULL)
            return NULL;

        AVIOContext *avio = fa_libav_reopen(fh);

        if((fctx = fa_libav_open_format(avio, url, NULL, 0, NULL)) == NULL) {
            fa_libav_close(avio);
            snprintf(errbuf, errlen, "Unable to open format");
            return NULL;
        }

        if(!strcmp(fctx->iformat->name, "avi"))
            fctx->flags |= AVFMT_FLAG_GENPTS;

        AVCodecContext *ctx = NULL;
        for(i = 0; i < fctx->nb_streams; i++) {
            if(fctx->streams[i]->codec != NULL &&
                    fctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
                ctx = fctx->streams[i]->codec;
                break;
            }
        }
        if(ctx == NULL) {
            fa_libav_close_format(fctx);
            return NULL;
        }

        AVCodec *codec = avcodec_find_decoder(ctx->codec_id);
        if(codec == NULL) {
            fa_libav_close_format(fctx);
            snprintf(errbuf, errlen, "Unable to find codec");
            return NULL;
        }

        if(avcodec_open(ctx, codec) < 0) {
            fa_libav_close_format(fctx);
            snprintf(errbuf, errlen, "Unable to open codec");
            return NULL;
        }

        ifv_close();

        ifv_stream = i;
        ifv_url = strdup(url);
        ifv_fctx = fctx;
        ifv_ctx = ctx;
    }

    AVPacket pkt;
    AVFrame *frame = avcodec_alloc_frame();
    int got_pic;


    AVStream *st = ifv_fctx->streams[ifv_stream];
    int64_t ts = av_rescale(sec, st->time_base.den, st->time_base.num);

    if(av_seek_frame(ifv_fctx, ifv_stream, ts, AVSEEK_FLAG_BACKWARD) < 0) {
        ifv_close();
        snprintf(errbuf, errlen, "Unable to seek to %"PRId64, ts);
        return NULL;
    }

    avcodec_flush_buffers(ifv_ctx);

#define MAX_FRAME_SCAN 500

    int cnt = MAX_FRAME_SCAN;
    while(1) {
        int r;

        r = av_read_frame(ifv_fctx, &pkt);

        if(r == AVERROR(EAGAIN))
            continue;

        if(r == AVERROR_EOF) {
            break;
        }
        if(r != 0) {
            ifv_close();
            break;
        }

        if(pkt.stream_index != ifv_stream) {
            av_free_packet(&pkt);
            continue;
        }
        cnt--;
        int want_pic = pkt.pts >= ts || cnt <= 0;

        ifv_ctx->skip_frame = want_pic ? AVDISCARD_DEFAULT : AVDISCARD_NONREF;

        avcodec_decode_video2(ifv_ctx, frame, &got_pic, &pkt);
        av_free_packet(&pkt);
        if(got_pic == 0 || !want_pic) {
            continue;
        }
        int w,h;

        if(im->req_width != -1 && im->req_height != -1) {
            w = im->req_width;
            h = im->req_height;
        } else if(im->req_width != -1) {
            w = im->req_width;
            h = im->req_width * ifv_ctx->height / ifv_ctx->width;

        } else if(im->req_height != -1) {
            w = im->req_height * ifv_ctx->width / ifv_ctx->height;
            h = im->req_height;
        } else {
            w = im->req_width;
            h = im->req_height;
        }

        pm = pixmap_create(w, h, PIX_FMT_RGB24,
#ifdef __PPC__
                           16
#else
                           1
#endif
                          );

        struct SwsContext *sws;
        sws = sws_getContext(ifv_ctx->width, ifv_ctx->height, ifv_ctx->pix_fmt,
                             w, h, PIX_FMT_RGB24, SWS_BILINEAR, NULL, NULL, NULL);
        if(sws == NULL) {
            ifv_close();
            snprintf(errbuf, errlen, "Scaling failed");
            pixmap_release(pm);
            return NULL;
        }

        uint8_t *ptr[4] = {0,0,0,0};
        int strides[4] = {0,0,0,0};

        ptr[0] = pm->pm_pixels;
        strides[0] = pm->pm_linesize;

        sws_scale(sws, (const uint8_t **)frame->data, frame->linesize,
                  0, ifv_ctx->height, ptr, strides);

        sws_freeContext(sws);

        if(pngencoder != NULL) {
            AVFrame *oframe = avcodec_alloc_frame();

            memset(&frame, 0, sizeof(frame));
            oframe->data[0] = pm->pm_pixels;
            oframe->linesize[0] = pm->pm_linesize;

            size_t outputsize = pm->pm_linesize * h;
            void *output = malloc(outputsize);
            pngencoder->width = w;
            pngencoder->height = h;
            pngencoder->pix_fmt = PIX_FMT_RGB24;

            r = avcodec_encode_video(pngencoder, output, outputsize, oframe);

            if(r > 0)
                blobcache_put(cacheid, "videothumb", output, r, INT32_MAX,
                              NULL, mtime);
            free(output);
            av_free(oframe);
        }
        break;
    }

    av_free(frame);
    if(pm == NULL)
        snprintf(errbuf, errlen, "Frame not found (scanned %d)",
                 MAX_FRAME_SCAN - cnt);
    return pm;
}
예제 #5
0
static pixmap_t *
fa_image_from_video2(const char *url0, const image_meta_t *im, 
		     const char *cacheid)
{
  pixmap_t *pm = NULL;
  char *url = mystrdupa(url0);
  char *tim = strchr(url, '#');

  *tim++ = 0;

  if(ifv_url == NULL || strcmp(url, ifv_url)) {
    // Need to open
    int i;
    AVFormatContext *fctx;
    AVIOContext *avio;
    
    if((avio = fa_libav_open(url, 65536, NULL, 0, 0)) == NULL)
      return NULL;

    if((fctx = fa_libav_open_format(avio, url, NULL, 0, NULL)) == NULL) {
      fa_libav_close(avio);
      return NULL;
    }

    if(!strcmp(fctx->iformat->name, "avi"))
      fctx->flags |= AVFMT_FLAG_GENPTS;

    AVCodecContext *ctx = NULL;
    for(i = 0; i < fctx->nb_streams; i++) {
      if(fctx->streams[i]->codec != NULL && 
	 fctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
	ctx = fctx->streams[i]->codec;
	break;
      }
    }
    if(ctx == NULL) {
      fa_libav_close_format(fctx);
      return NULL;
    }

    AVCodec *codec = avcodec_find_decoder(ctx->codec_id);
    if(codec == NULL) {
      fa_libav_close_format(fctx);
      return NULL;
    }

    if(avcodec_open(ctx, codec) < 0) {
      fa_libav_close_format(fctx);
      return NULL;
    }

    ifv_close();

    ifv_stream = i;
    ifv_url = strdup(url);
    ifv_fctx = fctx;
    ifv_ctx = ctx;
  }

  AVPacket pkt;
  AVFrame *frame = avcodec_alloc_frame();
  int got_pic;


  int secs = atoi(tim);

  AVStream *st = ifv_fctx->streams[ifv_stream];
  int64_t ts = av_rescale(secs, st->time_base.den, st->time_base.num);

  if(av_seek_frame(ifv_fctx, ifv_stream, ts, AVSEEK_FLAG_BACKWARD) < 0) {
    ifv_close();
    return NULL;
  }
  
  avcodec_flush_buffers(ifv_ctx);


  
  int cnt = 500;
  while(1) {
    int r;

    r = av_read_frame(ifv_fctx, &pkt);
    
    if(r == AVERROR(EAGAIN))
      continue;
    
    if(r == AVERROR_EOF)
      break;

    if(r != 0) {
      ifv_close();
      break;
    }

    if(pkt.stream_index != ifv_stream) {
      av_free_packet(&pkt);
      continue;
    }
    cnt--;
    int want_pic = pkt.pts >= ts || cnt <= 0;

    ifv_ctx->skip_frame = want_pic ? AVDISCARD_DEFAULT : AVDISCARD_NONREF;
    
    avcodec_decode_video2(ifv_ctx, frame, &got_pic, &pkt);
    if(got_pic == 0 || !want_pic)
      continue;

    int w,h;

    if(im->req_width != -1 && im->req_height != -1) {
      w = im->req_width;
      h = im->req_height;
    } else if(im->req_width != -1) {
      w = im->req_width;
      h = im->req_width * ifv_ctx->height / ifv_ctx->width;

    } else if(im->req_height != -1) {
      w = im->req_height * ifv_ctx->width / ifv_ctx->height;
      h = im->req_height;
    } else {
      w = im->req_width;
      h = im->req_height;
    }

    pm = pixmap_create(w, h, PIX_FMT_RGB24);

    struct SwsContext *sws;
    sws = sws_getContext(ifv_ctx->width, ifv_ctx->height, ifv_ctx->pix_fmt,
			 w, h, PIX_FMT_RGB24, SWS_LANCZOS, NULL, NULL, NULL);
    if(sws == NULL) {
      ifv_close();
      return NULL;
    }
    
    uint8_t *ptr[4] = {0,0,0,0};
    int strides[4] = {0,0,0,0};

    ptr[0] = pm->pm_pixels;
    strides[0] = pm->pm_linesize;

    sws_scale(sws, (const uint8_t **)frame->data, frame->linesize,
	      0, ifv_ctx->height, ptr, strides);

    sws_freeContext(sws);

    if(pngencoder != NULL) {
      AVFrame *oframe = avcodec_alloc_frame();

      memset(&frame, 0, sizeof(frame));
      oframe->data[0] = pm->pm_pixels;
      oframe->linesize[0] = pm->pm_linesize;
      
      size_t outputsize = pm->pm_linesize * h;
      void *output = malloc(outputsize);
      pngencoder->width = w;
      pngencoder->height = h;
      pngencoder->pix_fmt = PIX_FMT_RGB24;

      r = avcodec_encode_video(pngencoder, output, outputsize, oframe);
    
      if(r > 0) 
	blobcache_put(cacheid, "videothumb", output, outputsize, 86400 * 5);
      free(output);
      av_free(oframe);
    }
    break;
  }

  av_free(frame);
  return pm;
}