~ubuntu-branches/ubuntu/raring/forked-daapd/raring-proposed

« back to all changes in this revision

Viewing changes to src/artwork.c

  • Committer: Bazaar Package Importer
  • Author(s): Julien BLACHE
  • Date: 2011-04-09 11:41:55 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20110409114155-5i6vbc4v0eqtvcsg
Tags: 0.15-1
* New upstream release.

* debian/control:
  + Add build-dependency on gperf.
  + Bump Standards-Version to 3.9.2 (no changes).
* debian/copyright:
  + Update list of copyright holders.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (C) 2010 Julien BLACHE <jb@jblache.org>
 
2
 * Copyright (C) 2010-2011 Julien BLACHE <jb@jblache.org>
3
3
 *
4
4
 * This program is free software; you can redistribute it and/or modify
5
5
 * it under the terms of the GNU General Public License as published by
96
96
}
97
97
 
98
98
static int
99
 
artwork_rescale(AVFormatContext *src_ctx, int s, int out_w, int out_h, struct evbuffer *evbuf)
 
99
artwork_rescale(AVFormatContext *src_ctx, int s, int out_w, int out_h, int format, struct evbuffer *evbuf)
100
100
{
101
101
  uint8_t *buf;
102
102
  uint8_t *outbuf;
109
109
  AVStream *dst_st;
110
110
 
111
111
  AVCodec *img_decoder;
112
 
  AVCodec *png_encoder;
 
112
  AVCodec *img_encoder;
 
113
 
 
114
  int64_t pix_fmt_mask;
 
115
  const enum PixelFormat *pix_fmts;
113
116
 
114
117
  AVFrame *i_frame;
115
118
  AVFrame *o_frame;
156
159
      goto out_close_src;
157
160
    }
158
161
 
159
 
  dst_fmt->video_codec = CODEC_ID_PNG;
 
162
  dst_fmt->video_codec = CODEC_ID_NONE;
 
163
 
 
164
  /* Try to keep same codec if possible */
 
165
  if ((src->codec_id == CODEC_ID_PNG) && (format & ART_CAN_PNG))
 
166
    dst_fmt->video_codec = CODEC_ID_PNG;
 
167
  else if ((src->codec_id == CODEC_ID_MJPEG) && (format & ART_CAN_JPEG))
 
168
    dst_fmt->video_codec = CODEC_ID_MJPEG;
 
169
 
 
170
  /* If not possible, select new codec */
 
171
  if (dst_fmt->video_codec == CODEC_ID_NONE)
 
172
    {
 
173
      if (format & ART_CAN_PNG)
 
174
        dst_fmt->video_codec = CODEC_ID_PNG;
 
175
      else if (format & ART_CAN_JPEG)
 
176
        dst_fmt->video_codec = CODEC_ID_MJPEG;
 
177
    }
 
178
 
 
179
  img_encoder = avcodec_find_encoder(dst_fmt->video_codec);
 
180
  if (!img_encoder)
 
181
    {
 
182
      DPRINTF(E_LOG, L_ART, "No suitable encoder found for codec ID %d\n", dst_fmt->video_codec);
 
183
 
 
184
      ret = -1;
 
185
      goto out_close_src;
 
186
    }
160
187
 
161
188
  dst_ctx = avformat_alloc_context();
162
189
  if (!dst_ctx)
196
223
 
197
224
  dst->codec_id = dst_fmt->video_codec;
198
225
  dst->codec_type = CODEC_TYPE_VIDEO;
199
 
  dst->pix_fmt = PIX_FMT_RGB24;
 
226
 
 
227
  pix_fmt_mask = 0;
 
228
  pix_fmts = img_encoder->pix_fmts;
 
229
  while (pix_fmts && (*pix_fmts != -1))
 
230
    {
 
231
      pix_fmt_mask |= (1 << *pix_fmts);
 
232
      pix_fmts++;
 
233
    }
 
234
 
 
235
  dst->pix_fmt = avcodec_find_best_pix_fmt(pix_fmt_mask, src->pix_fmt, 1, NULL);
 
236
 
 
237
  if (dst->pix_fmt < 0)
 
238
    {
 
239
      DPRINTF(E_LOG, L_ART, "Could not determine best pixel format\n");
 
240
 
 
241
      goto out_free_dst;
 
242
      ret = -1;
 
243
    }
 
244
 
 
245
  DPRINTF(E_DBG, L_ART, "Selected pixel format: %d\n", dst->pix_fmt);
200
246
 
201
247
  dst->time_base.num = 1;
202
248
  dst->time_base.den = 25;
214
260
    }
215
261
 
216
262
  /* Open encoder */
217
 
  png_encoder = avcodec_find_encoder(dst_fmt->video_codec);
218
 
  if (!png_encoder)
219
 
    {
220
 
      DPRINTF(E_LOG, L_ART, "No suitable encoder found for PNG\n");
221
 
 
222
 
      ret = -1;
223
 
      goto out_free_dst;
224
 
    }
225
 
 
226
 
  ret = avcodec_open(dst, png_encoder);
 
263
  ret = avcodec_open(dst, img_encoder);
227
264
  if (ret < 0)
228
265
    {
229
266
      DPRINTF(E_LOG, L_ART, "Could not open codec for encoding: %s\n", strerror(AVUNERROR(ret)));
379
416
      goto out_fclose_dst;
380
417
    }
381
418
 
382
 
  ret = 0;
 
419
  switch (dst_fmt->video_codec)
 
420
    {
 
421
      case CODEC_ID_PNG:
 
422
        ret = ART_FMT_PNG;
 
423
        break;
 
424
 
 
425
      case CODEC_ID_MJPEG:
 
426
        ret = ART_FMT_JPEG;
 
427
        break;
 
428
 
 
429
      default:
 
430
        DPRINTF(E_LOG, L_ART, "Unhandled rescale output format\n");
 
431
        ret = -1;
 
432
        break;
 
433
    }
383
434
 
384
435
 out_fclose_dst:
385
436
  url_fclose(dst_ctx->pb);
409
460
}
410
461
 
411
462
static int
412
 
artwork_get(char *filename, int max_w, int max_h, struct evbuffer *evbuf)
 
463
artwork_get(char *filename, int max_w, int max_h, int format, struct evbuffer *evbuf)
413
464
{
414
465
  AVFormatContext *src_ctx;
415
466
  AVCodecContext *src;
417
468
  int target_w;
418
469
  int target_h;
419
470
  int need_rescale;
 
471
  int format_ok;
420
472
  int ret;
421
473
 
 
474
  DPRINTF(E_DBG, L_ART, "Artwork request parameters: max w = %d, max h = %d\n", max_w, max_h);
 
475
 
422
476
  ret = av_open_input_file(&src_ctx, filename, NULL, 0, NULL);
423
477
  if (ret < 0)
424
478
    {
436
490
      return -1;
437
491
    }
438
492
 
 
493
  format_ok = 0;
439
494
  for (s = 0; s < src_ctx->nb_streams; s++)
440
495
    {
441
496
      if (src_ctx->streams[s]->codec->codec_id == CODEC_ID_PNG)
442
 
        break;
 
497
        {
 
498
          format_ok = (format & ART_CAN_PNG) ? ART_FMT_PNG : 0;
 
499
          break;
 
500
        }
443
501
      else if (src_ctx->streams[s]->codec->codec_id == CODEC_ID_MJPEG)
444
 
        break;
 
502
        {
 
503
          format_ok = (format & ART_CAN_JPEG) ? ART_FMT_JPEG : 0;
 
504
          break;
 
505
        }
445
506
    }
446
507
 
447
508
  if (s == src_ctx->nb_streams)
495
556
 
496
557
  DPRINTF(E_DBG, L_ART, "Destination width %d height %d\n", target_w, target_h);
497
558
 
498
 
  /* Fastpath for PNG */
499
 
  if ((src->codec_id == CODEC_ID_PNG) && !need_rescale)
500
 
    ret = artwork_read(filename, evbuf);
 
559
  /* Fastpath */
 
560
  if (!need_rescale && format_ok)
 
561
    {
 
562
      ret = artwork_read(filename, evbuf);
 
563
      if (ret == 0)
 
564
        ret = format_ok;
 
565
    }
501
566
  else
502
 
    ret = artwork_rescale(src_ctx, s, target_w, target_h, evbuf);
 
567
    ret = artwork_rescale(src_ctx, s, target_w, target_h, format, evbuf);
503
568
 
504
569
  av_close_input_file(src_ctx);
505
570
 
514
579
 
515
580
 
516
581
static int
517
 
artwork_get_own_image(char *path, int max_w, int max_h, struct evbuffer *evbuf)
 
582
artwork_get_own_image(char *path, int max_w, int max_h, int format, struct evbuffer *evbuf)
518
583
{
519
584
  char artwork[PATH_MAX];
520
585
  char *ptr;
558
623
  if (i == (sizeof(cover_extension) / sizeof(cover_extension[0])))
559
624
    return -1;
560
625
 
561
 
  return artwork_get(artwork, max_w, max_h, evbuf);
 
626
  return artwork_get(artwork, max_w, max_h, format, evbuf);
562
627
}
563
628
 
564
629
static int
565
 
artwork_get_dir_image(char *path, int isdir, int max_w, int max_h, struct evbuffer *evbuf)
 
630
artwork_get_dir_image(char *path, int isdir, int max_w, int max_h, int format, struct evbuffer *evbuf)
566
631
{
567
632
  char artwork[PATH_MAX];
568
633
  char *ptr;
616
681
  if (i == (sizeof(cover_basename) / sizeof(cover_basename[0])))
617
682
    return -1;
618
683
 
619
 
  return artwork_get(artwork, max_w, max_h, evbuf);
620
 
}
621
 
 
622
 
 
623
 
int
624
 
artwork_get_item(int id, int max_w, int max_h, struct evbuffer *evbuf)
 
684
  return artwork_get(artwork, max_w, max_h, format, evbuf);
 
685
}
 
686
 
 
687
 
 
688
int
 
689
artwork_get_item_filename(char *filename, int max_w, int max_h, int format, struct evbuffer *evbuf)
 
690
{
 
691
  int ret;
 
692
 
 
693
  /* FUTURE: look at embedded artwork */
 
694
 
 
695
  /* Look for basename(filename).{png,jpg} */
 
696
  ret = artwork_get_own_image(filename, max_w, max_h, format, evbuf);
 
697
  if (ret > 0)
 
698
    return ret;
 
699
 
 
700
  /* Look for basedir(filename)/{artwork,cover}.{png,jpg} */
 
701
  ret = artwork_get_dir_image(filename, 0, max_w, max_h, format, evbuf);
 
702
  if (ret > 0)
 
703
    return ret;
 
704
 
 
705
  return -1;
 
706
}
 
707
 
 
708
int
 
709
artwork_get_item(int id, int max_w, int max_h, int format, struct evbuffer *evbuf)
625
710
{
626
711
  char *filename;
627
712
  int ret;
628
713
 
629
 
  DPRINTF(E_DBG, L_ART, "Artwork request for item %d, max w = %d, max h = %d\n", id, max_w, max_h);
 
714
  DPRINTF(E_DBG, L_ART, "Artwork request for item %d\n", id);
630
715
 
631
716
  filename = db_file_path_byid(id);
632
717
  if (!filename)
633
718
    return -1;
634
719
 
635
 
  /* FUTURE: look at embedded artwork */
636
 
 
637
 
  /* Look for basename(filename).{png,jpg} */
638
 
  ret = artwork_get_own_image(filename, max_w, max_h, evbuf);
639
 
  if (ret == 0)
640
 
    goto out;
641
 
 
642
 
  /* Look for basedir(filename)/{artwork,cover}.{png,jpg} */
643
 
  ret = artwork_get_dir_image(filename, 0, max_w, max_h, evbuf);
644
 
  if (ret == 0)
645
 
    goto out;
646
 
 
647
 
  DPRINTF(E_DBG, L_ART, "No artwork found for item id %d\n", id);
648
 
 
649
 
  ret = -1;
650
 
 
651
 
 out:
 
720
  ret = artwork_get_item_filename(filename, max_w, max_h, format, evbuf);
 
721
  if (ret < 0)
 
722
    DPRINTF(E_DBG, L_ART, "No artwork found for item id %d\n", id);
 
723
 
652
724
  free(filename);
 
725
 
653
726
  return ret;
654
727
}
655
728
 
656
729
int
657
 
artwork_get_group(int id, int max_w, int max_h, struct evbuffer *evbuf)
 
730
artwork_get_group(int id, int max_w, int max_h, int format, struct evbuffer *evbuf)
658
731
{
659
732
  struct query_params qp;
660
733
  struct db_media_file_info dbmfi;
662
735
  int got_art;
663
736
  int ret;
664
737
 
665
 
  DPRINTF(E_DBG, L_ART, "Artwork request for group %d, max w = %d, max h = %d\n", id, max_w, max_h);
 
738
  DPRINTF(E_DBG, L_ART, "Artwork request for group %d\n", id);
666
739
 
667
740
  /* Try directory artwork first */
668
741
  memset(&qp, 0, sizeof(struct query_params));
679
752
      goto files_art;
680
753
    }
681
754
 
682
 
  got_art = 0;
683
 
  while ((!got_art) && ((ret = db_query_fetch_string(&qp, &dir)) == 0) && (dir))
 
755
  got_art = -1;
 
756
  while ((got_art < 0) && ((ret = db_query_fetch_string(&qp, &dir)) == 0) && (dir))
684
757
    {
685
 
      got_art = ! artwork_get_dir_image(dir, 1, max_w, max_h, evbuf);
 
758
      got_art = artwork_get_dir_image(dir, 1, max_w, max_h, format, evbuf);
686
759
    }
687
760
 
688
761
  db_query_end(&qp);
689
762
 
690
763
  if (ret < 0)
691
764
    DPRINTF(E_LOG, L_ART, "Error fetching Q_GROUP_DIRS results\n");
692
 
  else if (got_art)
693
 
    return 0;
 
765
  else if (got_art > 0)
 
766
    return got_art;
694
767
 
695
768
 
696
769
  /* Then try individual files */
708
781
      return -1;
709
782
    }
710
783
 
711
 
  got_art = 0;
712
 
  while ((!got_art) && ((ret = db_query_fetch_file(&qp, &dbmfi)) == 0) && (dbmfi.id))
 
784
  got_art = -1;
 
785
  while ((got_art < 0) && ((ret = db_query_fetch_file(&qp, &dbmfi)) == 0) && (dbmfi.id))
713
786
    {
714
 
      got_art = ! artwork_get_own_image(dbmfi.path, max_w, max_h, evbuf);
 
787
      got_art = artwork_get_own_image(dbmfi.path, max_w, max_h, format, evbuf);
715
788
    }
716
789
 
717
790
  db_query_end(&qp);
718
791
 
719
792
  if (ret < 0)
720
793
    DPRINTF(E_LOG, L_ART, "Error fetching Q_GROUPITEMS results\n");
721
 
  else if (got_art)
722
 
    return 0;
 
794
  else if (got_art > 0)
 
795
    return got_art;
723
796
 
724
797
  return -1;
725
798
}